Tuesday, 10 November 2026

Chapter 3 — The Molt


Six fifty in the morning, the roller door chewed its rails all the way up, and the bay's day began with that one dull bang.


The overnight jobs already stood in a column on the whiteboard: two patrol machines with transmission noise, one hydrant pump seeping hydraulic fluid, and at the bottom a sheet circled twice in red. Unit Fourteen. Cockpit badge-interlock recert. Four days grounded. The duty ledger said OFF in one blunt word. Shift after shift had pushed it back and forth; the name line at the bottom right stayed empty.


A transfer sheet was pinned above it: 00:40, wholesale market, shelving collapse, filed as stack load. Two hundred kilos of canned goods had rolled across an aisle; the night crew had cleared them in under an hour; no injuries. She read it once and dropped back to her own sheet. Other people's accidents were not today's work.


The foreman slapped the sheet on her tool cart and spent no words on it. His ballpoint had filled out the duty roster so often the strokes sat in layers; what he had to say he said in sign-off columns. The bay's rule was more honest than its people: whoever takes the sheet signs it, and signs for it until delivery day. The sheet walked into her pocket on four words in the remarks line: the wiring is hers.


In this bay, that line was a pass and a noose in one. Half the interlock harnesses on the floor went through her hands; the rest had been dressed to her sample. When a machine came in broken like this, nobody else could reach the root of it, and she couldn't drop the root either. The last sheet like this one had carried her instructor's name on the sign-off line. From this sheet on, the first line was hers.


She wheeled the cart toward Unit Fourteen, extraction fans loud today, one tube in the ceiling row flickering. Past the parts locker somebody behind her dropped their voice low: "Heard your floor singing again?"


A short laugh followed, then everyone went back to work. The line had run since her first day in the shop. She hadn't answered from day one.


On the wall calendar, the grid for the day after tomorrow held one word: drill. Blue pen, small. She looked at it over her coffee, and let the look go.


Unit Fourteen sat on the stand with its chest and right shoulder plates off, stacked in trays. The canopy stood open. The smell of coolant and old leather carried three meters. She climbed in and laid her tools out left of the seat in order of use: hex set, side cutters, meter, electrical tape. Last came the jumper she had cut herself. Copper core, cold-crimped ends, two fingers shorter than her forearm. The shop's test leads ran long and stiff and turned a wrist to nothing in this narrow a bay. This one was her own, and when it was done it went back into her chest pocket with her own things.


The ignition board sat second row, right hand. The badge interlock filled three pages of regulation: the ignition line bound to the identity badge. Badge present, authority present. The rank stamped into it could not be peeled off, and the authority stayed with the badge. The machine follows the badge, not the face. She had written that footnote for this interlock three years ago and filed no exceptions since. She could recite the test procedure too: secondary tag on, master open, warning posted, prove zero volts. Four steps, in order, before the jumper earned its turn.


The jumper was the main act of the day.


She lifted the badge sample line off the terminal block and bared two cores. One end of the jumper went into the sample terminal, the other onto the test point. Thumb flat, eyes on the main screen. The cockpit went quiet enough to hear the fan behind the terminal block spin down, a second or two, and stop.


The green lamps climbed one notch at a time.


The answer bell rang, small and clean.


One word on the screen: NORMAL.


The engine did not speak. She worked down the checklist. Chocks under the road wheels where they had been all day. The pitch lock in its red tag. The master open as it had been since morning. The secondary tag swung cold against her collarbone. All of it by the book. The canopy had opened a seam, and the world behind the seam was one she had known since she was six.


She drew the jumper off and wound it back around her wrist. Testing a door, and walking through one, were two different jobs. That was the first thing this trade had taught her: don't mix them up. She signed the test sheet. One line above her name sat the previous signer, a mechanic with decent hands. In this shop, signatures always stood ahead of a technician's. Some of those signers had examined her work for years and never once taken her on.


The recert's last item was history. She dragged the scan window back to yesterday's small hours; twenty-four hours of vibration traces unrolled. At the stretch past three a.m. the scroll wheel stopped. She ran it back and played it again. Still there.


The shape matched nothing. She called up the vehicle library and compared: the twin hump of a freight hauler, the narrow spike of an auger rig, the sawtooth of a tracked platform. None of them fit. The amplitude sat low, but the rhythm was too steady, like somebody keeping count, beat for beat. She magnified the trace, shrank it, stretched the axis, flattened it. The count held. Half the shop compressor's cycle, and no off-beat of a ventilation fan either. No match was a no match. The machine sat dead, master open, the recorder alive on its own small battery. If the count had a source, it came from the ground.


No match meant no report. Instrument difference turned up daily. In the tag column she put INSTRUMENT DIFFERENCE. In the due column, thirty days. In small text under remarks: same segment next month, no repeat, close the file. The regulation ended there. She kept one private copy of that segment anyway, a screenshot filed at the bottom of a folder of her own. Nothing in the regulation said she couldn't keep a copy. Not to overturn anything. Against the day somebody came asking. She closed the data screen and knocked two soft knuckles on its bezel, for nothing.


Before knock-off she fed the harness back under the seat into its channel, and halfway there her hand stopped. The outer length of insulation had opened up, cut clean, as if with scissors. Three segments, equal lengths, the cut lips turned outward; the cuts were fresh, the copper not yet dull. She lit the flashlight along the bottom of the cockpit: no companion, no crumbs, not one extra grain of grit. She shot the cut ends, and added a last line to the remarks: pest damage, electrical. Cut away and cleared. Channel latched, locked, ladder down.


That evening Cassius had booked a table at the restaurant by the old-quarter gate. She said overtime; he asked, what overtime, the good hauling days don't wait. He won. She was hungry anyway.


The place had years on it; the chalkboard menu outside had been wiped and rewritten time and again, the lettering never changed. His old table: back of the room, a view of the door and none of the kitchen. The same instinct as his trading: price the risk first, then the yield. He'd come early; she could tell. Her water glass already filled, his seat out of the draft.


Before the dishes arrived he filled her water glass to seven-tenths, not a drop spilled, then walked her through the daytime drinks party and dealt the day's people: a son taking over a freight agency. Names at dealing speed. She mm-hmmed along; those names moved like the market, today's cards gone by tomorrow.


The lot on the hauling lane came up with the second course.


"That lane in the old quarter. The day it has to clear out, and I say that day is coming, everything on that street that can move rolls out inside one night." The back of his dinner knife tapped the plate rim, his smile climbing with the sound. "And by then, whoever holds the hauling capacity sets the terms. Whoever signs the manifest locks the price."


"By block of hours?" she asked.


"By night. The whole night." A snap of his fingers. "Glad to hear it. You understood."


She ran the sentence through her head like a ledger entry. Per block of hours was easy. The night itself was never written into a contract; the night lived in the market, and the market he knew better than anyone. She didn't take the thread.


 In these years, every sentence of his went through one round of conversion: what it was worth, what it had pledged. The conversion ran faster every year; it had startled her once. She slid the bread basket closer. "Slow down. Nobody's taking it off you."


He laughed and raised a hand for another basket of bread. When it came he tore most of the still-warm loaf into her plate and kept the heel for himself. The motion was natural and meant nothing by it, not the same man as the one pricing the haul, and she accepted it without taking it apart. The bread was still warm; she ate it slow. She had his whole pitch by heart without trying: three figures, two dates, one name. Which of the figures were true, the next month could say. The lamp behind his head laid his profile out even and bright, even the creases of his smile like something rehearsed. She thought of her own ceiling: lampless, filmed with an even layer of dust. 


At the bill he threw his card down in one open-handed gesture. Outside the door his phone rang; he glanced at the screen and tipped his chin at her. "The one across the river can't wait. Go on ahead, the taxi goes on my account." He took the call on the third ring, and the voice that came out was three degrees warmer than the street. His warmth came off a dial. She had seen that clearly.


The taxi let her out at the mouth of the old quarter, the restaurant's oven smoke chasing her half a block before the night wind folded it back. She walked the old streets the rest of the way.


The old quarter at night was tidy about its quiet. The last produce stall handed its final crates to a loader arm that stacked them into an unmanned van at the curb. The freezer bays plugged themselves into their charging pylons, indicator lights blinking in half-beats, the street handing itself over to the night grid. A night patrol drone slid along the curb, its lamp band laying a thin brightness on the damp. The one place still serving turned its sign-screen down a notch. From the crossing it was two streets to the building her grandmother had left her. The porch steps had taken a new handrail once, and the fourth step still answered a foot with the same knock as ten years back.


The crossing lamps printed the wet flagstones in long white strips. Ten twenty. A mid-size bus had just come through, its tire sound dragging a long way. The walk signal was empty; she stepped off while the count still ran. At the base of the wall sat a thing. First look said plastic, blown in by the wind; two steps closer took it back; plastic never comes this matte.


She was seven steps past it when her feet stopped on their own. She stood two seconds, turned, walked back, crouched down.


A shell. Whole. Forearm length, lying face-down, six legs folded, every crease of every leg joint in place, the underside unbroken, as if somebody had shed a coat that came with its own frame and set it neatly down. The back carried one seam, crown to tail, its film still wet, holding a single line of light. Empty inside. The wall of it thin enough to pass the shadow of her fingers through.


She ran her eyes down the wall, top to bottom. No second shell. No body. Nothing flying off. A close sniff read old plaster and dust, nothing else. The size matched nothing she had ever handled. This city's biggest roach never grew long enough to argue lengths with her forearm. Down flat, the flashlight's beam ran along the ground: the little patch of moss pinned under the rim still lived. Whatever this was, it had landed no more than a night past. That judgment she could afford. Moisture talks. Inside the rim a few shallow scrape marks, as if it had hauled itself out by its own grip. A quick measure: half an inch past her forearm. The rim's thickness ran uneven, thick across the back and thin along the belly. When you look at a thing, find the scale first. Occupational disease. Tonight's scale had borrowed her arm.


She didn't touch it. Not touching was bay doctrine: unknown origin, open a file, leave the scene. The thing that moved in the end wasn't her hand, it was the phone. Focus. One shot of the face. One of the flank. Two clicks, and the pictures filed themselves into the WORK album. The one album she kept: work items, and things shaped like work items. When the phone came down she looked around once. The crossing lamps steady, the street clock correct. The world going on as though it had countersigned the whole thing. Her hand rose halfway, and the rules put it back.


By the time she stood the sweeper truck had turned in, brushes riding the curb with a hiss of grit. A man in a reflective vest stepped down, and one broom stroke carried the shell into the dustpan with a lifetime's ease. "One of those props," he said to his partner on the truck. "Looks real, too. Halloween's not even here and they're test-fitting already."


The partner laughed. The brush sound moved off down the next block. Where tonight's dustpan went wasn't her business; she had watched it for one second.


She watched the road empty back to a shine. Then she said, under her breath, "Next week." And walked.


The building wasn't in sight yet when the sound started under her soles. Low. Even. Rising through the ball of the foot, like somebody turning over very far down. She slowed and walked on. Nineteen years she had carried this sound and never handed it to a second person. Not out of fear. There was no column for it: say it out loud, and which drawer does it file in? Tonight it ran lighter than usual, like a different way of breathing. She lent it half a beat of her attention and walked on.


Home. The shower first.


The red jacket slid off her shoulders, the tank top peeled off over her head, the denim shorts to her ankles. Hot water hammered down, and her skin flushed a thin pink in the fog. The water ran down the line of her neck, over the collarbones, over her chest, and bent at the hip. Her hands followed the water the way she traced a wiring diagram, knowing every line of this better than any drawing. The steam blurred the mirror into frosted glass.


She closed her eyes. The sound under the floor came up through the tile, lighter still than it had been outside, like something walking very slowly, very far down. Then the water got loud, and there was nothing else.


The water stopped. Towel over her hair, the front-room lamp still on. Cassius wasn't back, probably at some card table across the river.


In bed she set the phone face down, then turned it over once more. The WORK album sat open on tonight's two shots: face, flank. Swipe back, and there was the torque-spec sheet for Unit Fourteen, the thirty-day recheck reminder, and further back the close-up of the cut from the cockpit floor, untagged. She blew the two shell shots up one by one: the freshness of the split, the wet of the seam, the one clean split from crown to tail. At full zoom, fine rings ran across the surface of the shell, ring pressing on ring, the way growth rings run in a tree. Growth rings do not set up house under a street wall and leave no body behind. She tagged both photos: face. Flank. In the remarks field she thought for a moment, then added a line: next week.


Before lights-out, the thought she had kept down all day came back up. She didn't drive it off. She let it grow into two sentences:


If it was real, it had molted.

Thursday, 5 November 2026

Chapter 2 — Twelve Fifty-One

(This story is written by me and I will be posting it on Royal Road. Profile: https://www.royalroad.com/profile/1129550/fictions)


The cockpit again.

He knew it better than the room he rented. A fine scratch crossed the glass at the upper left of the instrument panel, as if someone had tested it with a fingernail. Half the lights in the third row stayed dark, the other half left unused on purpose. A shallow cut marked the leather on the right armrest. He knew every mark. This was not an old machine. The cockpit was newer, quieter, smarter than anything he had seen in Aredis. He had simply known it for longer than he had known any landlord in his building. Since he was six.

Every time he entered the dream, he did the same check. Left hand on the frame. Right hand over the three marks: scratch, half-lit row, shallow cut. A sentry making his rounds. There was no time in the dream, but he always felt the machine waiting for him to finish the count.

No sound. There had never been a voice in this dream. The machine was there. His hands knew it. Everything else was dark, and the dark had all the patience in the world.

He woke before the alarm.

A strip of blue-grey showed between the curtains. He watched the ceiling for three seconds, then reached for his phone. Two lunch orders, booked in advance: 12:10 and 12:51. He took both. He never turned down a pre-booked run. One rejection could shave half a point off his on-time score, and these were regulars. Same addresses every time; they barely bothered with notes. He liked those orders.

He needed to be at the prep counter by 12:44 for the later one. Seven minutes was the margin. Any earlier and the food would not be ready; any later and the bag sat waiting too long on the pickup shelf.

The bed frame creaked as he got up. The room woke with him. In this rented place, only two things made noise: the bed frame and Lucan.

He washed, pulled on his riding clothes, wound the charging cable twice and tucked it into the side pocket of his bag. He tapped the dust from his helmet lining. Before leaving, he looked back into the room. There was nothing to see. He looked anyway.

Too much riding, he told himself. Every morning, the same excuse for the dream. He never changed the wording.

At 6:12 he rode up onto the pavement and slipped past a garbage truck stuck at the light. He knew this stretch without looking. One ring of the bell and people moved. Dogs, too.

Aredis in the morning was a city at knee height. Cabbages rose to a market seller's waist. Fish flashed in the tanks. Steam from the breakfast stalls slid along the tiles. Lucan cut through the middle without using his horn. The bell was enough. Horns were for people who did not know the road.

He had ridden this street a hundred times. Vera had probably walked it as often, he thought. Speed changed what you saw. She might notice the stalls and the sky; he looked for a gap wide enough to pass through, a loose paving stone that would kick his back wheel sideways, a kitchen door that let out soup at half past six. He had delivered to that shop so often he could tell how many portions were in the pot by the smell.

He liked the market just after it opened. Every stall smelled like breakfast, even if he usually had to ride on before he could eat any. He kept a breakfast ranking: pepper broth at the corner, first; fried dough two stalls down, second. On a rare day off, he'd try something new and see if it could beat the broth. No app could rate breakfast. The broth led by half a point, though he was open to appeals.

He rarely looked up. Riders did not watch the sky; people who watched it had time to spare. He caught the freight shuttles and their fading trails in the corner of his eye, the same things he imagined Vera saw when she looked up.

A ball rolled into his path. The child came after it. Lucan braked, put one foot down and waited until the kid had the ball before riding on. The first lesson this job taught him was not how to find an address. It was to stop half a beat before everyone else.

The shortcut ran beneath a covered arcade. Air-conditioning units dripped overhead; the paving stayed damp all year. The old man who watched the far end lifted one eyelid when Lucan passed. That counted as a greeting. The cut-through saved two minutes. Two minutes meant money.

Rent in five days. He ran yesterday's take: the platform's cut, a battery swap, the visor he still had not replaced. Its crack climbed from the lower left like lightning frozen in ice. Through it, every red light looked doubled. He had tested it; he followed the one on the right. The money home stayed the same. His family had never asked if it was enough; he had never said it wasn't. He put his phone away and took the next order.

At 12:44, at the prep counter, he opened the insulated carrier and touched the pickup shelf. Dry.

He checked the pickup shelf every time. Other riders glanced and moved on. Lucan thought the note "don't spill the drink" had been written for a day exactly like this.

He folded a napkin twice and slid it under the sauce cup. The cup sat secure in its holder. Her tea: light ice. Months ago, she had mentioned it once to the room, as if talking to the air. He happened to hear and remembered the two words.

Then the chili sachet.

He took one from the little compartment and folded it into the napkin. Months ago, while waiting at the workshop counter for a signature, he had heard her say to the room, "I want something spicy." Her wrench kept moving. She never ordered chili herself. Maybe she'd felt awkward once she'd said it out loud. So he slipped a sachet into her bag. He had never told her.

The food was ready. He sealed the bag and stuck the label on.

The name at the top was VERA P., his LUCAN underneath. Her eyes passed over his name as if it were a phone number. He told himself he was used to it.

At the workshop door, he checked the destination rack's dry corner. A pipe leaked every winter and had stained the wall black on the rack's left end. He was the only courier who checked the dry corner before setting down a bag. He had noticed the leak last winter while sheltering from the rain. Vera had been there too, cursing the pipe: "Every year." She had not been talking to him. He remembered the words anyway. Since then, checking that corner had become his craft. He could do it more reliably than the app could keep time.

At 12:51, he set the bag down in the rack's dry corner and made sure all four corners sat flat.

She did not look up. "Leave it there, thanks."

In that half-second, he almost said her name. Vera. He had practised it once inside his helmet and never tried again. He had made himself a rule: if she ever looked up at him first, he would say it. She never had.

The handle of his insulated carrier pressed a groove into his palm. The app would record the delivery time. The pause had lasted half a second; turning away took him two full seconds. He imagined she had measured it too. He had no proof.

The delivery door closed behind him with a chime. He left the half-second inside, as if nothing had happened.

He never waited for the lift. He never changed an address or invented a reason to come by the workshop. When the app sent him one of her orders, he worked the rest of his route around it. He left the bag at the door and went.

At lunch, the riders gathered in their usual place and compared ratings. One customer had left him three stars with the note: "Soup spilled." It had been sealed. He had checked it; the photo on his phone showed it intact, the shot steady. He did not appeal. Uploading it, filling out a form and waiting for someone he would never meet to decide was time he could not spare.

The new kid had a 4.99. Lucan said, "Four point nine eight."

"You care about a hundredth?"

"It's the closest thing I've got to a promotion."

Someone told him to take airport runs. The fares were better.

"Not on my route," Lucan said.

"Your home isn't near the airport either."

"No. Home's not on the way to the airport."

The answer came quicker than thought. He had rehearsed it for a different kind of detour, one only he knew about.

At three, the workshop's coffee order came through. The foreman ordered the same thing every day: black, no sugar. Lucan had made this delivery often enough to know where to park and where the foreman wanted the cup. Hydraulic oil, then coffee.

The shutter was half open. He parked beyond the yellow line, carried the coffee inside and checked the whiteboard. The foreman tipped his head toward the table. Lucan put the cup in its usual corner. He had done it so many times he could have cut a key by feel.

Then he saw her.

She stood in the middle of the floor.

The room was full of noise: the compressor, a pneumatic wrench, the grinder farther back, someone's music, a mechanic at station three swearing at a bolt that would not catch. But she was listening to something else. Her head tilted. Her shoulders lifted a little. Lucan knew the look. It was what a person did when she lent her whole body to her ears.

He stopped and counted to five. One, two, three, four, five.

He heard nothing.

He could list every sound in the room: the compressor in two long bursts and a short one; the wrench in threes; the song reaching its chorus again; the mechanic changing his curse after the third word. Four sounds. Nothing more. He did not know what the fifth one was. He only knew that she had heard it, and that for him, the four were everything.

Maybe the floor really was making a noise. When he reached five, all he could hear was the workshop. Not one sound more, not one less. At the door, a new kid called out, "Heard it again? Your floor." Vera ignored him. The others turned back with grins.

The new kid saw Lucan and raised his chin. "You think she really hears something?"

Lucan lifted the coffee. "I hear you lot making a racket."

He finished the handoff without laughing or joining in. They had made enough jokes about her already. He had stood in the same place for five seconds and heard nothing; at least this time, he had not laughed along.

Back on his bike, the seat was still hot from the afternoon sun. He did not start the engine right away. He looked once at the shutter. Was she still standing in the middle of the floor? He did not know. He only knew his own ears had been empty for five seconds, and that he had stood there for nothing.

His last run before seven was to the hospital. The night nurse took the bag and thanked him. Her eyes were red. He did not ask why. A rider's rule: other people's red eyes were not his business.

Outside the hospital doors, the wind tugged his collar open. Only then did he realize he had been holding his breath.

His last delivery was after dark.

He took the covered arcade shortcut. The air-conditioning units that dripped all day had gone quiet. In the alley he could hear only his tires crossing the damp paving. Halfway through, he squeezed the brake.

A beetle clung to the wall.

Not an ordinary one. It was as big as a crouching person. Its wing cases were folded tight, all six legs hooked into the gaps between the bricks. It was as black as the alley. If he had not ridden this cut-through every day, if he did not know each brick by sight, it might have been part of the wall.

He slowed to half speed.

Halloween prop, he thought. Those were popular this year, the kind that crawled up walls. The hardware shop had a row of them outside. Their eyes lit up, too.

He rode on.

Twenty metres past it, a chill reached the back of his neck. He could not have said what was wrong. He tugged his collar higher and repeated Halloween to himself. Right. Halloween.

His front wheel bumped over a tile at the mouth of the alley. He did not look back.

That night, the cockpit again.

He knew where every instrument sat. He lifted his hand, and the fine scratch waited under his fingertip. He had dreamed this cockpit for nearly twenty years. Since six: machine there, hands knowing, no voices, not a word. Once he had fallen asleep gripping a wrench, trying to bring something into the dream with him. He woke with the wrench under his pillow. Nothing had followed him in.

When he was six, he told an adult about the dream. Children had strange dreams, they said. He stopped bringing it up, but the dream stayed with him for twenty years.

He had waited for the cockpit to change. A light coming on would have been enough. A seat turning a few degrees. Nothing ever did. He had nearly got used to that.

Tonight was different.

Before he reached for it, the control stick moved.

Only two inches, toward him. No sound. Nothing in that dream made a sound, which made the movement plain as a mark scratched into the dark. He started to reach. Before his hand moved, the stick shifted another half-inch, as if it knew.

Not a fault. A test. Something asking: Are you still there?

He woke with his hand raised, fingers spread, reaching into empty air.

The room was exactly as he had left it. The charging cable in his bag. His helmet on the stool. Nothing moved. Nothing could explain that two-and-a-half-inch shift. He checked his phone: 2:47. Tomorrow's orders were already lining up.

Aredis outside the curtain was black as a sheet. He lay still for a while, then lowered his hand to the blanket. The dream did not come back. It never worked overtime.

He turned his palm over and studied it. There was nothing in the lines of it, but the weight of that two-and-a-half-inch shift was still there, like something he had carried a long way and did not dare set down.

Too much riding, he told himself again. He did not believe it either.

The two and a half inches stayed in his palm. He rolled onto his side and closed his hand around them.

Chapter 1 — The Word at 4 A.M.


(This story is written by me and I will be posting it on Royal Road. Profile: https://www.royalroad.com/profile/1129550/fictions)



The cockpit knew her hands.

Every switch on the console was a shape she had never seen before, and her fingers went
there anyway. Thumb to the ignition plate. Two fingers to the trim wheel. Palm flat on
the smooth panel where no seam showed. Pale light filled the canopy, the color of deep
sky a breath after the sun leaves it, and the stick settled into her grip as if it had
been poured there.

She ran the preflight out of order, the way she always did in the dream, and the
console agreed with every wrong step. Somewhere outside the canopy a voice said something
patient and unfinished, the way a person keeps talking to a machine that is already
listening.

4:07. The dream let go.

Vera lay in the bed she had grown up in, in the apartment her grandmother had left her
three streets from the old quarter, and listened. The floor was humming again. Ducts?
The neighbor's compressor? Or an old quarter settling in the night, because old quarters
do that. Three good explanations, none of them worth chasing once she was awake.

She had been six the first time, in this same room, listening to a floor that never
stopped working. The cockpit never changed, and her hands never forgot it. She rolled
over and named the hum to herself (geothermal line, definitely the geothermal line).

The movement woke him, or gave him the excuse he always used.

"Still flying?" Cassius murmured, without opening his eyes.

He remembered. Three months ago she had come out of one of those dreams and told him
the whole impossible thing, switches she had never seen and hands that knew them
anyway, and he had listened the way he listened to the stories that cost him nothing,
and asked about it ever since. It was possibly the only thing he remembered about her
shifts, her floor, her.

Something in her unclenched. She turned to him, found his mouth in the dark, and the
kiss he gave back was still half asleep: warm, unhurried, certain of where it was
going, the way everything with Cassius began.

What followed had the shape everything with him had: he was certain first. His hand went
under her shirt and traveled the line of her ribs, the way a man traces a blueprint he
owns. She felt his mouth on her jaw, her throat, and last the hollow behind her ear,
where one touch could break a sentence in half, and his other hand pinned her hip to
the mattress she had grown up on. The shirt came off over her head and the dark took it somewhere. His skin
was already warm, already faintly damp, and he was in no hurry except about breathing,
which he did against her collarbone until her body answered first and her mind
followed willingly.

She had always liked this about him: wanting showed up in his whole body, openly, with
nothing kept back for later. He went after what he wanted wholeheartedly, cheerfully, and for himself. Clothes were a problem solved and then not
a problem. His weight settled over her, solid and deliberate, a man who filled the whole
room around her, and when he started to ask whether she wanted him to stop, she pulled
him down by the shoulder and answered the question with her mouth.

He laughed once, low, and the laugh broke into a gasp where she moved under him. The
bed, old and opinionated about weight, began to creak in a rhythm it had never learned
from her alone, and under it the floor kept up its own low hum, and neither sound
had anything to say to the other. Her hands went down his back and counted nothing.
His mouth found the underside of her jaw and stayed there, and every time she stopped
thinking, the cockpit loosened its grip on her fingers by one more.

Past talking, past the point where either of them would have bothered with words, the
rhythm narrowed into a thing with no language in it. Faster now. Her breaths broke into smaller pieces; his stayed even. The peak came through them both like a door
swinging on one hinge, all at once and in one direction, and after that she was gone to
a place the cockpit had never once let her into.

He was asleep in under a minute, arm thrown across her waist like a claim staked.
Cassius could sleep the way he did everything: instantly, and without apology. She lay
listening to his breathing stacked over the floor's low hum, one hum on top of the
other, and felt the old room settle around them. Her right hand lay open on the sheet,
curled around nothing, still holding a stick that existed nowhere in this city.

Six forty, alarm. The city had been awake for two hours without her.

Aredis woke on time, as it did every morning. At 6:42 the first cargo shuttle crossed
the river, its contrails over the hangars. On the market road, the patrol machine walked
its route past the fish vendors, a house on legs, its joints too quiet to rattle the crates.
A kid on a stack of boxes waved. The machine raised a hand half a beat late, as always.
Nobody looked up from their cabbages.

Vera's walk to work took six minutes. She knew the route's cracks: the step that iced
first, the courier who mounted the curb, the old woman who fed pigeons and had never
learned Vera's name.

She had walked this route at every hour. Six in the morning was her favorite: the city
with its collar down, belonging to nobody. At twenty-five, she had a handsome trader at
home who called her grease-stained mechanic work a cute phase. If that counted as a life, the cabbages still
had to be moved.

Four minutes off the clock, at the market crossing, a small van went sideways
into a cabbage truck and the lane closed like a fist. Nobody was hurt; the cabbages had
lost. Vera swore, checked the time, and went around the long way. The bay never noticed
her late. The bay never noticed much.

Morning in the bay: work orders, radiator, coffee that
tasted like the log book. The foreman did not look up from his screen. "Model agency
called. They want their face back."

"Tell them I'm booked till retirement."

Her face had got her free coffees and extra scrutiny for as long as she could count, and
she had stopped keeping score. In the dark window over the filing cabinets she saw
herself: pretty face, harder mouth, and the mouth was the part that settled things.

Unit Six had been up on its stand since yesterday, a knock nobody could place, three
men arguing hydraulics over lunch like men at a racetrack. She let them spend their
coffee, put her ear against the hip actuator, and had the loose panel bolted in nine
minutes: the same nine minutes the day shift had spent agreeing the fault was
intermittent.

Someone told her another week of days, and her request to swap to nights got the
same "not yet". The pilot course had been a "not yet"
for three years running, and the not-yet always wore the same warm face: the force
trains its own, the academy keeps the list, the bay is where you are useful. She was
useful. The word sat in her like a bolt that looks seated and isn't.

Past the roller door, a patrol machine went by on its way to nothing in particular, and
she watched it longer than she needed to.

On her break she did the thing she never mentioned: climbed into Unit Two's dead
cockpit, hands on sticks she could rebuild blindfolded, and sat through lunch while the
bay ate around her. The ignition was wired to her badge, and her badge said mechanic.
So she sat, and the machine offered exactly what it offered everyone: nothing. Since
she was six, she had dreamed of this. The cockpit in her sleep was always kinder.

12:51, her phone lit up with the lunch run.

The bag hit the rack by the door with a knock she could have picked out of any noise in
the building. She was on the third rewrite of a work order about a patrol machine that
had put its knee through a shopfront, fault or pilot error being the disputed part.

"Leave it there, thanks."

She did not look up. She never looked up, she realized around the fourth month of
never looking up.

The rack's left end stayed dark from the pipe that leaked every winter. The bag sat on
the dry corner, as it always did, never the wet side. The drink carrier was wedged so
nothing could tip it, a napkin folded under the sauce cup so the cup could not slide on
the walk over. Her tea, light ice, once said out loud to the room, months ago, in the
middle of three other sentences, to nobody.

The order line on the bag read VERA P., and under it the courier's name: LUCAN, read
the way people read phone numbers: straight through, kept for nobody. She tapped delivered and went
back to the work order.

There was a chili sachet again. She had not ordered chili since the day she mentioned
wanting some over her shoulder at the counter, a perfectly normal thing to say to thin
air, and saying it out loud made ordering it feel too obvious. Since then the sachet arrived folded under the napkin every time, square
and red and unexplained.

The delivery door chimed shut behind him. Half a second later, she noticed the half second: there was always one
at the end of the delivery, a pause where whoever it was stood like a man about to say
something, in a job where nobody ever said anything, because the app had already said
it. Rain, she told herself. Weather. She had a work order to fix, and by the time she looked at
the door, the door was only a door.

Nineteen hundred, shift over. She did not go home.

She sat in with the night crew: machines were going with
the contractors to clear the salvage lane tonight or not at all, and somebody had to
listen to them work. Half for the paperwork. Half because the apartment hummed louder
than the bay, and at least here the hum had coffee.

Twenty-one hundred, a drunk on the pier and his fishing photos.
Twenty-two forty, the vending machine and the rookie's playlist. She was
into the night log when the radio came alive at 00:40. Shelving collapse, wholesale
market, no injuries reported, two hundred kilos of canned goods across the delivery lane.

Unit Four was already rolling. Its cabin smelled of vinyl and the coffee of three
previous shifts, and the seat had been worn into somebody else's shape. The operator had
eleven years on the machine and none of them interested him, and he walked it down the
empty avenue in long flat strides that made the streetlights sway.

Inside the wholesale market, the machine's arm put a pallet of cans two inches from a
wall and held it there while the crew kicked crates in underneath. The night crew
treated it as furniture that happened to move.
Nobody looked up at Unit Four the way the kid looked up at the morning patrol, because
at three in the morning nobody looked up at anything.

From the second seat, every movement the machine made looked effortless, which was
exactly what the dream felt like and what she could not have while awake.

In the dream, she flies something nobody ever showed her, and her hands know things her
head never learned, and the machine answers before she finishes wanting it to. Here she
watched another man's hands fight a grip that fought back, in a cabin that smelled of
other people's shifts, and the machine was a good machine, a municipal machine, and it
was the wrong machine in every direction. It had weight, it had noise, it argued. The
dream did not argue. The dream agreed with her about everything, and she had never once
been able to bring a single detail of it out into the light.

A foreman walked beside her with a clipboard, spending the whole walk on how this would
cost him his bonus and must go on the record that he had reported it.
She let him spend it all: a man who has just lost his bonus will sign anything, provided
you let him finish the sentence first. Eleven seconds. The lane opened by 01:20.

Back at the bay at 02:30, the break room had tea going and the floor doing it
again.

It was a low thing, below hearing, more felt than heard: knees first, teeth second.
She tilted her ear without meaning to, and the juniors pounced: heard it again? Her
floor. The old crew no longer took the bait, the way people stop taking up an old joke.

"So your floor was singing again?" the rookie needled. "My grandmother swore the
same thing: the old quarter sings, like it's proud of something."

"Vents," said the old mechanic, not looking up from his log book.

"Rent," the rookie said. "So old, even the floor's got a landlord."

Then the rookie leaned in. Three weeks on the job, still pleased to be awake at this hour. "You want the real one? The Blue God."

"Older than the city, maybe older than the war. Sleeping under the oldest streets, blue as deep sky." He stopped for a drink. Nobody hurried him.

"Priests went down to wake it and came back empty-handed. Mayors, too. A monument stands downtown, but no one knows when it was erected. Engineers drilled nine hundred meters. The bit came back coated in blue dust. No geologist would sign the report."

"Every telling ends the same way: it doesn't hate you. It hasn't woken, and it won't wake for you."

"It isn't angry," the rookie finished. "It just doesn't answer. That's almost worse."

"Every bit that ever bit old rock comes back blue," the old mechanic said. "Page four
of every report I filed. If there's a god down there, it owes me rent."

They turned with grins, the way rooms do when a question travels. "Vera. You grew up three streets
from the old quarter. Did the floor ever sing to you?"

"Heard it plenty." She set her cup down. "Never got an answer either."

The room went back to its tea. Nobody asked her what she meant, which she preferred, and which was also, she thought,
the only riddle she had ever solved about this city: people stopped asking exactly one question short of the answer.

Three ten, she walked home.

Sodium lamps on wet asphalt. The patrol machine standing dark at the junction, off duty,
hands empty, looking smaller without anyone watching it. Stars thinning toward morning.
Her own steps, her own breath, years of nights in a city that never thanked her for
staying up.

The apartment key, the kitchen light, the same three steps from the door to the counter.
And there on the tile: a cockroach, big as a thumbnail, dark as a freshly minted coin. She raised
her foot.

It did not run. It turned to face her and held, a half beat past the point where
insects hold anything, the way a listening thing holds.

Her stomp found bare tile. Under the stove, most likely, already. The light, the hour,
twelve hours of shift. She told herself she had simply missed, and did not find the
thought as comforting as she meant it to be.

She put the kettle on. The tea went cold beside her. She did not remember getting into bed. Sleep came down
like a thrown switch.

Cockpit. Pale light. And now the voice, patient as before, spoke in the Old Tongue,
the language every child here grew up understanding without ever being taught. It came
through the canopy padding from everywhere at once, still saying its unfinished thing.
She understood it the way you understand your own name called from another room: not
translating, just knowing, and reaching.

Then the voice put all its weight on a single word, once, like a stamp pressed into
the center of her chest.

Corath.

4:07.

Vera lay with her eyes open. The bed beside her rose and fell on Cassius's breathing,
unbroken. The word sat inside her. She had simply never turned around to look at it. She did not know it. She had never
heard it. It was not in any language she had studied or any prayer she had been taught,
and it did not feel foreign, and that was worse. Foreign she could have thrown out.

She got up and stood at the sink for no reason she would have admitted to. Over the
sink, the window stood open two fingers wide to the night. Vesper hung low above the roofline. Everyone called it the evening star, and at four
in the morning it had no business still being up.

There it was anyway, keeping hours nobody had taught it.

Behind her, on the floor of the kitchen, nothing hummed. Or rather, something did, and
she had run out of explanations that were worth the trouble of saying out loud.

Monday, 17 January 2022

Difference between "docker stop" and "docker kill"

 To stop a running container, you can use either "docker stop" or "docker kill" command to do so. Although it seems doing the same thing, actually there is a slight difference between them.

"docker stop" command will send a hardware signal SIGTERM to the container, if the process received the SIGTERM signal, the developer can code to do some clean up and releasing some resources before terminating the process.

However "docker kill" command will send a hardware signal SIGKILL to the container and stop it immediately.

Usually "docker stop" is used to stop a running container. If the container is hanging there for a long time or failed to stop. Then you can try to use "docker kill"to kill the container anyway.

Sunday, 26 December 2021

Why do we need an accordant pace in computer systems

In the past, we always know clock is used to adjust the pace of the computer systems. But we don't understand why we need an accordant pace in computer systems. Why don't we just let the components in the computer do as much and fast as they can?

The reason is that the different components have dependency between each other. So if we image the whole computer systems is a succession program, of course we don't need accordant pace any more. But this will make the components in computer wait for each other's result to go on. So this can't make components work in parallel way.

So obviously clock has this advantage which is that it can make different components work in parallel way become possible.

Sunday, 28 November 2021

DO NOT use the return of append function to create new slice in Go

For Golang developers, it is very common to use append function to append new elements into slice. The common syntax is like below:

    var slice := make([]int, 0)
    slice = append(slice, 123)
And for some requirements, you may want to create a new slice based on an existing slice. We know the below the code will work perfectly.
    slice := []int{1,2,3}
    newSlice := make([]int, 0)
    newSlice = append(newSlice, append(slice, 4)...)
Below is complete example code to show the result:
package main

import (
    "fmt"
)

func main() {
    // here create the origin slice with cap 10 to make sure that
    // the slice is big enough to hold more data
    slice := make([]int, 0, 10)
    slice = append(slice, []int{1, 2, 3}...)
    newSlice := make([]int, 0)
    newSlice = append(newSlice, append(slice, 4)...)
    fmt.Println(slice)
    fmt.Println(newSlice)
    fmt.Printf("The address of slice: %v\n", &slice[0])
    fmt.Printf("The address of newSlice: %v\n", &newSlice[0])
}
The result is:
[1 2 3]
[1 2 3 4]
The address of slice: 0xc000014050
The address of newSlice: 0xc00007a000
You can see the two slices have different addresses.
However you may think if we can simplify the code by appending value to the origin slice and assign the return value to the newSlice variable like below:
    slice := []int{1,2,3}
    newSlice := make([]int, 0)
    newSlice = append(slice, 4)
This looks simpler and cleaner, right? NO, this won't work! Let's see an example:
package main

import (
    "fmt"
)

func main() {
    // here create the origin slice with cap 10 to make sure that
    // the slice is big enough to hold more data
    slice := make([]int, 0, 10)
    slice = append(slice, []int{1, 2, 3}...)
    newSlice := make([]int, 0)
    newSlice = append(slice, 4)
    fmt.Println(slice)
    fmt.Println(newSlice)
    fmt.Printf("The address of slice: %v\n", &slice[0])
    fmt.Printf("The address of newSlice: %v\n", &newSlice[0])
}
The result is:
[1 2 3]
[1 2 3 4]
The address of slice: 0xc00010a000
The address of newSlice: 0xc00010a000
See newSlice is pointing to the same address of slice?

This is because append function does not guarantee that it always returns a new slice. It only reallocate a new slice when the capacity of the slice in the first parameter is not enough to hold more data. So if you are expecting to use append function to get a new slice like above, you will probably mess up the origin slice and get the wrong output.
So to be safe, if you want to get a new slice based on an existing slice, you use the code below:
    slice := []int{1,2,3}
    newSlice := make([]int, 0)
    newSlice = append(newSlice, append(slice, 4)...)
Or below code if it is clearer.
    slice := []int{1,2,3}
    newSlice := make([]int, 0)
    newSlice = append(newSlice, slice...)
    newSlice = append(newSlice, 4)
I encountered this problem when I am practicing LeetCode problem 797. 



Wednesday, 17 November 2021

How to add optional arguments in Go function without impacting the existing function calls

Unlike C# you can put "Optional" keyword to add optional arguments in function, there is no direct way to create optional parameters in Go functions. And there is no method overloading in Go either. Even so, if you really need to add optional arguments to an existing function, maybe because this function is in a common library which is called by different software modules and you don't want to update all the modules for this new argument change, there is still a way to implement optional arguments thanks to variadic arguments in Go functions.

Variadic arguments allow developer to put any number of trailing arguments as the input of functions. For example:

package main

import (
  "fmt"
)

func main() {
  fmt.Printf("1 + 2 = %d\n", add(1, 2))
  fmt.Printf("1 + 2 + 3 + 4 + 5 = %d\n", add(1, 2, 3, 4, 5))
}

func add(args ...int) int {
  sum := 0
  for i:=0; i < len(args); i++ {
    sum += args[i]
  }
  return sum
}
The output is:
1 + 2 = 3
1 + 2 + 3 + 4 + 5 = 15
With the help of variadic arguments, you can easily to implement optional arguments. For example, you have a function to generate characters in a common library for a game development. This function can generate characters with name and sex for now. 
package main

import (
  "fmt"
)

func main() {
  createCharactor("Bertram", "Male")
}

func createCharactor(name string, sex string) {
  fmt.Println("---------- New Charactor ----------")
  fmt.Printf("Name is: %s\n", name)
  fmt.Printf("Sex is: %s\n", sex)
  fmt.Println("------ New Charactor Created ------")
}
The output is: 
---------- New Charactor ----------
Name is: Bertram
Sex is: Male
------ New Charactor Created ------
Now you want to add age argument to this function without impacting the existing function call. You can do like following:
package main

import (
  "fmt"
)

func main() {
  createCharactor("Bertram", "Male")
  fmt.Println()
  createCharactor("Kai", "Male", 15)
}

func createCharactor(name string, sex string, age ...int) {
  fmt.Println("---------- New Charactor ----------")
  fmt.Printf("Name is: %s\n", name)
  fmt.Printf("Sex is: %s\n", sex)
  if len(age) > 0 {
    fmt.Printf("Age is: %d\n", age[0])
  }
  fmt.Println("------ New Charactor Created ------")
}
The output is:
---------- New Charactor ----------
Name is: Bertram
Sex is: Male
------ New Charactor Created ------

---------- New Charactor ----------
Name is: Kai
Sex is: Male
Age is: 15
------ New Charactor Created ------
But the above code is not reusable to add other arguments with different data types. For example, what if you need to add title, email later? So in order to make the variadic argument more generic, we can use "interface{}" type as the variadic argument which gives the ability to add more arguments with different data types.

According to this, the above code can be refactored as below:
package main

import (
  "fmt"
)

func main() {
  createCharactor("Bertram", "Male")
  fmt.Println()
  createCharactor("Kai", "Male", 15, "Software Engineer", "kai@gmail.com")
  fmt.Println()
	
}

func createCharactor(name string, sex string, args ...interface{}) {
  fmt.Println("---------- New Charactor ----------")
  fmt.Printf("Name is: %s\n", name)
  fmt.Printf("Sex is: %s\n", sex)
  if len(args) > 0 {
    fmt.Printf("Age is: %d\n", args[0].(int))
    fmt.Printf("Tile is: %s\n", args[1].(string))
    fmt.Printf("Email is: %s\n", args[2].(string))
  }
  fmt.Println("------ New Charactor Created ------")
}
The output is:
---------- New Charactor ----------
Name is: Bertram
Sex is: Male
------ New Charactor Created ------

---------- New Charactor ----------
Name is: Kai
Sex is: Male
Age is: 15
Tile is: Software Engineer
Email is: kai@gmail.com
------ New Charactor Created ------

However, this solution does not convey the meaning of the optional arguments. So you either put a comment above the header to specify what it means for each optional argument, or comment where you call the functions, otherwise it will become very difficult to understand the code. So this solution is not recommended unless you have a very tight deadline to meet the delivery date and really have no time to refactor code.  

Sunday, 24 October 2021

Pointer Receiver vs Value Receiver

Receivers are same as parameters in function in Go. They are also passed by value when functions are called. Because of this, it is preferred to use pointers as receivers instead of passing values directly. This is because usually we use receivers to implement OOP programming style. If passed by value, the properties of the objects will not be able to update.

For example, we have an object called "person", it has age property. Initially when created, the person has initialised the age to 0, then we use method to change it to 18. See code below:

package main

import (
	"fmt"
)

type Person struct {
	Name string
	Age int
}

func main() {
	person := Person{Name : "Leo"}
	fmt.Println(person)
	person.SetAge(18)
	fmt.Println(person)
	
}

func (p *Person) SetAge(age int) {
	p.Age = age
}
The output of the result is:
{Leo 0}
{Leo 18}
However if the receiver is passed by value like below:

func (p Person) SetAge(age int) {
	p.Age = age
}

Then the age property will not be updated. However if the receiver is passed by value like below:

{Leo 0}
{Leo 0}

Sunday, 3 October 2021

Variables and Data Types in Javascript

This is a study note about Javascript from https://www.geeksforgeeks.org/introduction-to-javascript-course-learn-how-to-build-a-task-tracker-using-javascript/

Javascript is untyped language. Once a variable is created in javascript using 'var', you can assign any other type of data to this variable.

var text = 'Hello World'
text = 123

Above code is valid in Javascript. Variable text can be assigned a string value and then later change to a number.

1. Difference between var and let in Javascript

Basically, 'var' is function scoped, however 'let' is block scoped.

https://www.geeksforgeeks.org/difference-between-var-and-let-in-javascript/

Let's use use 'let' for most of the cases because 'var' is confusing.

2. Number type in Javascript

The number type in Javascript contains both integer and floating point numbers. Besides these numbers, we also have 'special-numbers' in Javascript that are: 'infinity', '-Infinity' and 'NaN'. The 'NaN' denotes a computational error.

let num = 2; // integer
let num2 = 1.3; // floating point number
let num3 = Infinity; // Infinity
let num4 = 'something here too'/2; // NaN

3. String type in Javascript

There are three types of quotes in Javascript:

let str = "Hello There";
let str2 = 'Single quotes works fine';
let phrase = `can embed ${str}`;

There's no difference between 'single' and "double" quotes in Javascript. Backticks provide extra functionality as with the help of them we can embed variables inside them.

let variable = "Leo";

// embed a variable
alert( `Hello, ${variable}!` ); // Hello, Leo!

4, Undefined type in Javascript

The meaning of undefined is 'value is not assigned'.

let x;
console.log(x); // undefined

5, Object type in Javascript

Everything in Javascript is Object. There are two ways to create objects.

let person = new Object();
let person = {};

You can initialise object with properties like below:

let person = {
name: "Mukul",
age: 22,
}







Sunday, 13 June 2021

Mistakes That Should Not Happen Again

 Database:

DO NOT use "key" keyword as a column name, because it is a reserved keyword in MySQL.


Docker:

Clean docker using below command from time to time to release more memory:

docker system prune

Then type u and press "enter".





Monday, 12 April 2021

Channels in Go

 This is a study note for YouTube tutorial: https://www.youtube.com/watch?v=YS4e4q9oBaU&t=20036s


Channel basics

You can only create channels using make function.

ch := make(chan int) // chan int means create a integer channel

Below is an example how to use channel to transfer data between goroutines.

var wg = sync.WaitGroup{}

func main() {
ch := make(chan int)
wg.Add(2)
go func() {
i := <-ch
fmt.Println(i)
wg.Done()
}()
go func() {
ch <- 42
wg.Done()
}()
wg.Wait()
}

The result is:
42


Restricting data flow

Be noted that channel operation will block the goroutine when executing. If you have unequal receiver and sender, then the additional goroutines will be blocked and give runtime errors.

func main() {
ch := make(chan int)
wg.Add(3)
go func() {
i := <-ch
fmt.Println(i)
wg.Done()
}()
go func() {
ch <- 42
wg.Done()
}()
go func() {
ch <- 27
wg.Done()
}()
wg.Wait()
}

27 fatal error: all goroutines are asleep - deadlock!

You can use bidirectional communication using channel in goroutines.

func main() {
ch := make(chan int)
wg.Add(2)
go func() {
i := <-ch
fmt.Println(i)
ch <- 27
wg.Done()
}()
go func() {
ch <- 42
fmt.Println(<-ch)
wg.Done()
}()

wg.Wait()
}

42 27

Goroutines can automatically manage the directions of the communication. However in most cases, we would like to make channel in single directions, which means one goroutine is dedicated to be receiver and another be a sender. To do this, you can put channel as function parameter for goroutine to restrict the data flow. Because function parameter can be used to cast a bi channel to a single direction channel.

func main() {
ch := make(chan int)
wg.Add(2)
go func(ch <-chan int) { // Here actually cast bi channel to receiver channel
i := <-ch
fmt.Println(i)
wg.Done()
}(ch)
go func(ch chan<- int) {
ch <- 42
wg.Done()
}(ch)

wg.Wait()
}

42

Now the first goroutine is restricted to receive-only, and the second is restricted to send-only.

Buffered channels

You can add a buffer for a channel by simply specifying the second parameter of make function with buffer size.

var wg = sync.WaitGroup{}

func main() {
ch := make(chan int, 50)
wg.Add(2)
go func(ch <-chan int) {
i := <-ch
fmt.Println(i)
wg.Done()
}(ch)
go func(ch chan<- int) {
ch <- 42
ch <- 27
wg.Done()
}(ch)

wg.Wait()
}

27 will be buffered instead of throwing a "deadlock" error.



For...range loops with channels

The above code is not a correct way to handle buffered channels. "for...range" loops is preferred in this case.

var wg = sync.WaitGroup{}

func main() {
ch := make(chan int, 50)
wg.Add(2)
go func(ch <-chan int) {
for i := range ch {
fmt.Println(i)
}
wg.Done()
}(ch)
go func(ch chan<- int) {
ch <- 42
ch <- 27
wg.Done()
}(ch)

wg.Wait()
}

The result is:

42 27 fatal error: all goroutines are asleep - deadlock!

You can see there is "deadlock" error again, but this time it is not because of the sender goroutine, it is because of the for range loop in the receiver goroutine. Because the receiver goroutine keeps trying to receive data even there is no data sent anymore.

To solve this problem, you can use "close(ch)" function to close channel in the sender goroutine if there is no data to send anymore

var wg = sync.WaitGroup{}

func main() {
ch := make(chan int, 50)
wg.Add(2)
go func(ch <-chan int) {
for i := range ch {
fmt.Println(i)
}
wg.Done()
}(ch)
go func(ch chan<- int) {
ch <- 42
ch <- 27
close(ch)
wg.Done()
}(ch)

wg.Wait()
}

The result is:

42 27

In fact, channel has a second return value which you can use for checking if the channel is open or closed.

var wg = sync.WaitGroup{}

func main() {
ch := make(chan int, 50)
wg.Add(2)
go func(ch <-chan int) {
for {
if i, ok := <-ch; ok {
fmt.Println(i)
} else {
break
}
}
wg.Done()
}(ch)
go func(ch chan<- int) {
ch <- 42
ch <- 27
close(ch)
wg.Done()
}(ch)

wg.Wait()
}

The result is:

42 27


Select statements

You can use a select statement to manage the workflow in a goroutine. Select statement is similar to switch statement, but select statement is only used for communications. The case statement refers to the communications on different channels.

var logCh = make(chan string)
var doneCh = make(chan struct{})

func main() {
go logger()

logCh <- "test1"
logCh <- "test2"
time.Sleep(100 * time.Millisecond)
doneCh <- struct{}{} // empty struct used as a signal here
}

func logger() {
for {
select {
case log := <-logCh:
fmt.Println(log)
case <-doneCh:
break
}
}
}


References: https://www.youtube.com/watch?v=YS4e4q9oBaU&t=20036s

Chapter 3 — The Molt

Six fifty in the morning, the roller door chewed its rails all the way up, and the bay's day began with that one dull bang. The overnigh...