[{"data":1,"prerenderedAt":3120},["ShallowReactive",2],{"page-\u002Fgo\u002F18-select-and-multiplexing":3},{"id":4,"title":5,"body":6,"description":3113,"extension":3114,"meta":3115,"navigation":94,"path":3116,"seo":3117,"stem":3118,"__hash__":3119},"content\u002Fgo\u002F18-select-and-multiplexing.md","18 — Select & Multiplexing",{"type":7,"value":8,"toc":3107},"minimark",[9,13,21,26,3103],[10,11,5],"h1",{"id":12},"_18-select-multiplexing",[14,15,16,20],"p",{},[17,18,19],"code",{},"select"," is Go's concurrent control flow — it waits on multiple channel operations, proceeding with whichever is ready first.",[22,23,25],"h2",{"id":24},"select-mechanics","Select Mechanics",[27,28,30,325,333,3028,3090,3094],"code-wrapper",{"language":29},"go",[31,32,36],"pre",{"className":33,"code":34,"language":29,"meta":35,"style":35},"language-go shiki shiki-themes github-light github-dark","\u002F\u002F ┌──────────────────────────────────────────────────────────────────────┐\n\u002F\u002F │ select chooses ONE ready case:                                       │\n\u002F\u002F │   - If multiple cases are ready, picks ONE at RANDOM (no priority)   │\n\u002F\u002F │   - If no case is ready and no default → BLOCKS until one is ready   │\n\u002F\u002F │   - If no case is ready and default present → runs default           │\n\u002F\u002F │   - A nil channel case → never ready (disabled)                     │\n\u002F\u002F │   - `select {}` (no cases, no default) → blocks forever             │\n\u002F\u002F └──────────────────────────────────────────────────────────────────────┘\n\nfunc selectBasics() {\n    ch1 := make(chan int, 1)\n    ch2 := make(chan int, 1)\n    ch1 \u003C- 1\n\n    select {\n    case v := \u003C-ch1:\n        fmt.Println(\"from ch1:\", v)\n    case v := \u003C-ch2:\n        fmt.Println(\"from ch2:\", v)\n    case \u003C-time.After(5 * time.Second):\n        fmt.Println(\"timeout\")\n    default:\n        fmt.Println(\"nothing ready (non-blocking)\")\n    }\n}\n","",[17,37,38,47,53,59,65,71,77,83,89,96,111,142,164,175,180,189,206,224,238,252,276,290,299,313,319],{"__ignoreMap":35},[39,40,43],"span",{"class":41,"line":42},"line",1,[39,44,46],{"class":45},"sdCPZ","\u002F\u002F ┌──────────────────────────────────────────────────────────────────────┐\n",[39,48,50],{"class":41,"line":49},2,[39,51,52],{"class":45},"\u002F\u002F │ select chooses ONE ready case:                                       │\n",[39,54,56],{"class":41,"line":55},3,[39,57,58],{"class":45},"\u002F\u002F │   - If multiple cases are ready, picks ONE at RANDOM (no priority)   │\n",[39,60,62],{"class":41,"line":61},4,[39,63,64],{"class":45},"\u002F\u002F │   - If no case is ready and no default → BLOCKS until one is ready   │\n",[39,66,68],{"class":41,"line":67},5,[39,69,70],{"class":45},"\u002F\u002F │   - If no case is ready and default present → runs default           │\n",[39,72,74],{"class":41,"line":73},6,[39,75,76],{"class":45},"\u002F\u002F │   - A nil channel case → never ready (disabled)                     │\n",[39,78,80],{"class":41,"line":79},7,[39,81,82],{"class":45},"\u002F\u002F │   - `select {}` (no cases, no default) → blocks forever             │\n",[39,84,86],{"class":41,"line":85},8,[39,87,88],{"class":45},"\u002F\u002F └──────────────────────────────────────────────────────────────────────┘\n",[39,90,92],{"class":41,"line":91},9,[39,93,95],{"emptyLinePlaceholder":94},true,"\n",[39,97,99,103,107],{"class":41,"line":98},10,[39,100,102],{"class":101},"svdQ7","func",[39,104,106],{"class":105},"sIsaT"," selectBasics",[39,108,110],{"class":109},"ssxIu","() {\n",[39,112,114,117,120,123,126,129,132,135,139],{"class":41,"line":113},11,[39,115,116],{"class":109},"    ch1 ",[39,118,119],{"class":101},":=",[39,121,122],{"class":105}," make",[39,124,125],{"class":109},"(",[39,127,128],{"class":101},"chan",[39,130,131],{"class":101}," int",[39,133,134],{"class":109},", ",[39,136,138],{"class":137},"snvgF","1",[39,140,141],{"class":109},")\n",[39,143,145,148,150,152,154,156,158,160,162],{"class":41,"line":144},12,[39,146,147],{"class":109},"    ch2 ",[39,149,119],{"class":101},[39,151,122],{"class":105},[39,153,125],{"class":109},[39,155,128],{"class":101},[39,157,131],{"class":101},[39,159,134],{"class":109},[39,161,138],{"class":137},[39,163,141],{"class":109},[39,165,167,169,172],{"class":41,"line":166},13,[39,168,116],{"class":109},[39,170,171],{"class":101},"\u003C-",[39,173,174],{"class":137}," 1\n",[39,176,178],{"class":41,"line":177},14,[39,179,95],{"emptyLinePlaceholder":94},[39,181,183,186],{"class":41,"line":182},15,[39,184,185],{"class":101},"    select",[39,187,188],{"class":109}," {\n",[39,190,192,195,198,200,203],{"class":41,"line":191},16,[39,193,194],{"class":101},"    case",[39,196,197],{"class":109}," v ",[39,199,119],{"class":101},[39,201,202],{"class":101}," \u003C-",[39,204,205],{"class":109},"ch1:\n",[39,207,209,212,215,217,221],{"class":41,"line":208},17,[39,210,211],{"class":109},"        fmt.",[39,213,214],{"class":105},"Println",[39,216,125],{"class":109},[39,218,220],{"class":219},"sJ6F3","\"from ch1:\"",[39,222,223],{"class":109},", v)\n",[39,225,227,229,231,233,235],{"class":41,"line":226},18,[39,228,194],{"class":101},[39,230,197],{"class":109},[39,232,119],{"class":101},[39,234,202],{"class":101},[39,236,237],{"class":109},"ch2:\n",[39,239,241,243,245,247,250],{"class":41,"line":240},19,[39,242,211],{"class":109},[39,244,214],{"class":105},[39,246,125],{"class":109},[39,248,249],{"class":219},"\"from ch2:\"",[39,251,223],{"class":109},[39,253,255,257,259,262,265,267,270,273],{"class":41,"line":254},20,[39,256,194],{"class":101},[39,258,202],{"class":101},[39,260,261],{"class":109},"time.",[39,263,264],{"class":105},"After",[39,266,125],{"class":109},[39,268,269],{"class":137},"5",[39,271,272],{"class":101}," *",[39,274,275],{"class":109}," time.Second):\n",[39,277,279,281,283,285,288],{"class":41,"line":278},21,[39,280,211],{"class":109},[39,282,214],{"class":105},[39,284,125],{"class":109},[39,286,287],{"class":219},"\"timeout\"",[39,289,141],{"class":109},[39,291,293,296],{"class":41,"line":292},22,[39,294,295],{"class":101},"    default",[39,297,298],{"class":109},":\n",[39,300,302,304,306,308,311],{"class":41,"line":301},23,[39,303,211],{"class":109},[39,305,214],{"class":105},[39,307,125],{"class":109},[39,309,310],{"class":219},"\"nothing ready (non-blocking)\"",[39,312,141],{"class":109},[39,314,316],{"class":41,"line":315},24,[39,317,318],{"class":109},"    }\n",[39,320,322],{"class":41,"line":321},25,[39,323,324],{"class":109},"}\n",[22,326,328,329,332],{"id":327},"timeout-timeafter-and-the-leak","Timeout — ",[17,330,331],{},"time.After"," and the Leak",[27,334,335,622,626],{"language":29},[31,336,338],{"className":33,"code":337,"language":29,"meta":35,"style":35},"\u002F\u002F ❌ time.After leaks — the timer goroutine lingers until it fires,\n\u002F\u002F even if the select took another case. In a hot loop, this accumulates.\nfunc timeoutBad(input \u003C-chan int) {\n    for {\n        select {\n        case v := \u003C-input:\n            process(v)\n        case \u003C-time.After(2 * time.Second):\n            fmt.Println(\"timeout\")\n        }\n    }\n}\n\u002F\u002F Each iteration creates a new time.After timer. If input fires frequently,\n\u002F\u002F each unused timer lingers for 2 seconds → thousands of leaked timers.\n\n\u002F\u002F ✅ time.NewTimer + Stop — clean up the timer explicitly\nfunc timeoutGood(input \u003C-chan int) {\n    timer := time.NewTimer(2 * time.Second)\n    defer timer.Stop()\n\n    for {\n        timer.Reset(2 * time.Second)  \u002F\u002F reset for each iteration\n        select {\n        case v := \u003C-input:\n            process(v)\n        case \u003C-timer.C:\n            fmt.Println(\"timeout\")\n        }\n    }\n}\n\u002F\u002F timer.Stop() in the defer cleans up. timer.Reset() reuses the same timer.\n",[17,339,340,345,350,371,378,385,399,407,426,439,444,448,452,457,462,466,471,488,510,524,528,534,554,560,572,578,588,601,606,611,616],{"__ignoreMap":35},[39,341,342],{"class":41,"line":42},[39,343,344],{"class":45},"\u002F\u002F ❌ time.After leaks — the timer goroutine lingers until it fires,\n",[39,346,347],{"class":41,"line":49},[39,348,349],{"class":45},"\u002F\u002F even if the select took another case. In a hot loop, this accumulates.\n",[39,351,352,354,357,359,363,366,368],{"class":41,"line":55},[39,353,102],{"class":101},[39,355,356],{"class":105}," timeoutBad",[39,358,125],{"class":109},[39,360,362],{"class":361},"sCrzJ","input",[39,364,365],{"class":101}," \u003C-chan",[39,367,131],{"class":101},[39,369,370],{"class":109},") {\n",[39,372,373,376],{"class":41,"line":61},[39,374,375],{"class":101},"    for",[39,377,188],{"class":109},[39,379,380,383],{"class":41,"line":67},[39,381,382],{"class":101},"        select",[39,384,188],{"class":109},[39,386,387,390,392,394,396],{"class":41,"line":73},[39,388,389],{"class":101},"        case",[39,391,197],{"class":109},[39,393,119],{"class":101},[39,395,202],{"class":101},[39,397,398],{"class":109},"input:\n",[39,400,401,404],{"class":41,"line":79},[39,402,403],{"class":105},"            process",[39,405,406],{"class":109},"(v)\n",[39,408,409,411,413,415,417,419,422,424],{"class":41,"line":85},[39,410,389],{"class":101},[39,412,202],{"class":101},[39,414,261],{"class":109},[39,416,264],{"class":105},[39,418,125],{"class":109},[39,420,421],{"class":137},"2",[39,423,272],{"class":101},[39,425,275],{"class":109},[39,427,428,431,433,435,437],{"class":41,"line":91},[39,429,430],{"class":109},"            fmt.",[39,432,214],{"class":105},[39,434,125],{"class":109},[39,436,287],{"class":219},[39,438,141],{"class":109},[39,440,441],{"class":41,"line":98},[39,442,443],{"class":109},"        }\n",[39,445,446],{"class":41,"line":113},[39,447,318],{"class":109},[39,449,450],{"class":41,"line":144},[39,451,324],{"class":109},[39,453,454],{"class":41,"line":166},[39,455,456],{"class":45},"\u002F\u002F Each iteration creates a new time.After timer. If input fires frequently,\n",[39,458,459],{"class":41,"line":177},[39,460,461],{"class":45},"\u002F\u002F each unused timer lingers for 2 seconds → thousands of leaked timers.\n",[39,463,464],{"class":41,"line":182},[39,465,95],{"emptyLinePlaceholder":94},[39,467,468],{"class":41,"line":191},[39,469,470],{"class":45},"\u002F\u002F ✅ time.NewTimer + Stop — clean up the timer explicitly\n",[39,472,473,475,478,480,482,484,486],{"class":41,"line":208},[39,474,102],{"class":101},[39,476,477],{"class":105}," timeoutGood",[39,479,125],{"class":109},[39,481,362],{"class":361},[39,483,365],{"class":101},[39,485,131],{"class":101},[39,487,370],{"class":109},[39,489,490,493,495,498,501,503,505,507],{"class":41,"line":226},[39,491,492],{"class":109},"    timer ",[39,494,119],{"class":101},[39,496,497],{"class":109}," time.",[39,499,500],{"class":105},"NewTimer",[39,502,125],{"class":109},[39,504,421],{"class":137},[39,506,272],{"class":101},[39,508,509],{"class":109}," time.Second)\n",[39,511,512,515,518,521],{"class":41,"line":240},[39,513,514],{"class":101},"    defer",[39,516,517],{"class":109}," timer.",[39,519,520],{"class":105},"Stop",[39,522,523],{"class":109},"()\n",[39,525,526],{"class":41,"line":254},[39,527,95],{"emptyLinePlaceholder":94},[39,529,530,532],{"class":41,"line":278},[39,531,375],{"class":101},[39,533,188],{"class":109},[39,535,536,539,542,544,546,548,551],{"class":41,"line":292},[39,537,538],{"class":109},"        timer.",[39,540,541],{"class":105},"Reset",[39,543,125],{"class":109},[39,545,421],{"class":137},[39,547,272],{"class":101},[39,549,550],{"class":109}," time.Second)  ",[39,552,553],{"class":45},"\u002F\u002F reset for each iteration\n",[39,555,556,558],{"class":41,"line":301},[39,557,382],{"class":101},[39,559,188],{"class":109},[39,561,562,564,566,568,570],{"class":41,"line":315},[39,563,389],{"class":101},[39,565,197],{"class":109},[39,567,119],{"class":101},[39,569,202],{"class":101},[39,571,398],{"class":109},[39,573,574,576],{"class":41,"line":321},[39,575,403],{"class":105},[39,577,406],{"class":109},[39,579,581,583,585],{"class":41,"line":580},26,[39,582,389],{"class":101},[39,584,202],{"class":101},[39,586,587],{"class":109},"timer.C:\n",[39,589,591,593,595,597,599],{"class":41,"line":590},27,[39,592,430],{"class":109},[39,594,214],{"class":105},[39,596,125],{"class":109},[39,598,287],{"class":219},[39,600,141],{"class":109},[39,602,604],{"class":41,"line":603},28,[39,605,443],{"class":109},[39,607,609],{"class":41,"line":608},29,[39,610,318],{"class":109},[39,612,614],{"class":41,"line":613},30,[39,615,324],{"class":109},[39,617,619],{"class":41,"line":618},31,[39,620,621],{"class":45},"\u002F\u002F timer.Stop() in the defer cleans up. timer.Reset() reuses the same timer.\n",[22,623,625],{"id":624},"the-for-select-loop-the-standard-pattern","The For-Select Loop — The Standard Pattern",[27,627,628,936,940],{"language":29},[31,629,631],{"className":33,"code":630,"language":29,"meta":35,"style":35},"\u002F\u002F Most concurrent Go code is a for loop containing a select.\n\u002F\u002F ALWAYS include a done\u002Fctx.Done() case for the exit path.\n\nfunc worker(ctx context.Context, input \u003C-chan int, output chan\u003C- int) error {\n    for {\n        select {\n        case v, ok := \u003C-input:\n            if !ok {\n                return nil  \u002F\u002F input closed — clean exit\n            }\n            select {\n            case output \u003C- process(v):\n            case \u003C-ctx.Done():\n                return ctx.Err()  \u002F\u002F cancelled while sending\n            }\n        case \u003C-ctx.Done():\n            return ctx.Err()  \u002F\u002F cancelled\n        }\n    }\n}\n\n\u002F\u002F ⚠️ `break` in a for-select only breaks the select, not the for loop!\n\u002F\u002F Use `return` or a labeled break to exit the loop:\nfunc forSelectBreak() {\nloop:\n    for {\n        select {\n        case \u003C-done:\n            break loop  \u002F\u002F ✅ labeled break exits the for loop\n        case v := \u003C-ch:\n            process(v)\n        }\n    }\n}\n",[17,632,633,638,643,647,694,700,706,719,730,741,746,753,769,784,800,804,816,830,834,838,842,846,851,856,865,870,876,882,891,902,915,921,926,931],{"__ignoreMap":35},[39,634,635],{"class":41,"line":42},[39,636,637],{"class":45},"\u002F\u002F Most concurrent Go code is a for loop containing a select.\n",[39,639,640],{"class":41,"line":49},[39,641,642],{"class":45},"\u002F\u002F ALWAYS include a done\u002Fctx.Done() case for the exit path.\n",[39,644,645],{"class":41,"line":55},[39,646,95],{"emptyLinePlaceholder":94},[39,648,649,651,654,656,659,662,665,668,670,672,674,676,678,681,684,686,689,692],{"class":41,"line":61},[39,650,102],{"class":101},[39,652,653],{"class":105}," worker",[39,655,125],{"class":109},[39,657,658],{"class":361},"ctx",[39,660,661],{"class":105}," context",[39,663,664],{"class":109},".",[39,666,667],{"class":105},"Context",[39,669,134],{"class":109},[39,671,362],{"class":361},[39,673,365],{"class":101},[39,675,131],{"class":101},[39,677,134],{"class":109},[39,679,680],{"class":361},"output",[39,682,683],{"class":101}," chan\u003C-",[39,685,131],{"class":101},[39,687,688],{"class":109},") ",[39,690,691],{"class":101},"error",[39,693,188],{"class":109},[39,695,696,698],{"class":41,"line":67},[39,697,375],{"class":101},[39,699,188],{"class":109},[39,701,702,704],{"class":41,"line":73},[39,703,382],{"class":101},[39,705,188],{"class":109},[39,707,708,710,713,715,717],{"class":41,"line":79},[39,709,389],{"class":101},[39,711,712],{"class":109}," v, ok ",[39,714,119],{"class":101},[39,716,202],{"class":101},[39,718,398],{"class":109},[39,720,721,724,727],{"class":41,"line":85},[39,722,723],{"class":101},"            if",[39,725,726],{"class":101}," !",[39,728,729],{"class":109},"ok {\n",[39,731,732,735,738],{"class":41,"line":91},[39,733,734],{"class":101},"                return",[39,736,737],{"class":137}," nil",[39,739,740],{"class":45},"  \u002F\u002F input closed — clean exit\n",[39,742,743],{"class":41,"line":98},[39,744,745],{"class":109},"            }\n",[39,747,748,751],{"class":41,"line":113},[39,749,750],{"class":101},"            select",[39,752,188],{"class":109},[39,754,755,758,761,763,766],{"class":41,"line":144},[39,756,757],{"class":101},"            case",[39,759,760],{"class":109}," output ",[39,762,171],{"class":101},[39,764,765],{"class":105}," process",[39,767,768],{"class":109},"(v):\n",[39,770,771,773,775,778,781],{"class":41,"line":166},[39,772,757],{"class":101},[39,774,202],{"class":101},[39,776,777],{"class":109},"ctx.",[39,779,780],{"class":105},"Done",[39,782,783],{"class":109},"():\n",[39,785,786,788,791,794,797],{"class":41,"line":177},[39,787,734],{"class":101},[39,789,790],{"class":109}," ctx.",[39,792,793],{"class":105},"Err",[39,795,796],{"class":109},"()  ",[39,798,799],{"class":45},"\u002F\u002F cancelled while sending\n",[39,801,802],{"class":41,"line":182},[39,803,745],{"class":109},[39,805,806,808,810,812,814],{"class":41,"line":191},[39,807,389],{"class":101},[39,809,202],{"class":101},[39,811,777],{"class":109},[39,813,780],{"class":105},[39,815,783],{"class":109},[39,817,818,821,823,825,827],{"class":41,"line":208},[39,819,820],{"class":101},"            return",[39,822,790],{"class":109},[39,824,793],{"class":105},[39,826,796],{"class":109},[39,828,829],{"class":45},"\u002F\u002F cancelled\n",[39,831,832],{"class":41,"line":226},[39,833,443],{"class":109},[39,835,836],{"class":41,"line":240},[39,837,318],{"class":109},[39,839,840],{"class":41,"line":254},[39,841,324],{"class":109},[39,843,844],{"class":41,"line":278},[39,845,95],{"emptyLinePlaceholder":94},[39,847,848],{"class":41,"line":292},[39,849,850],{"class":45},"\u002F\u002F ⚠️ `break` in a for-select only breaks the select, not the for loop!\n",[39,852,853],{"class":41,"line":301},[39,854,855],{"class":45},"\u002F\u002F Use `return` or a labeled break to exit the loop:\n",[39,857,858,860,863],{"class":41,"line":315},[39,859,102],{"class":101},[39,861,862],{"class":105}," forSelectBreak",[39,864,110],{"class":109},[39,866,867],{"class":41,"line":321},[39,868,869],{"class":109},"loop:\n",[39,871,872,874],{"class":41,"line":580},[39,873,375],{"class":101},[39,875,188],{"class":109},[39,877,878,880],{"class":41,"line":590},[39,879,382],{"class":101},[39,881,188],{"class":109},[39,883,884,886,888],{"class":41,"line":603},[39,885,389],{"class":101},[39,887,202],{"class":101},[39,889,890],{"class":109},"done:\n",[39,892,893,896,899],{"class":41,"line":608},[39,894,895],{"class":101},"            break",[39,897,898],{"class":109}," loop  ",[39,900,901],{"class":45},"\u002F\u002F ✅ labeled break exits the for loop\n",[39,903,904,906,908,910,912],{"class":41,"line":613},[39,905,389],{"class":101},[39,907,197],{"class":109},[39,909,119],{"class":101},[39,911,202],{"class":101},[39,913,914],{"class":109},"ch:\n",[39,916,917,919],{"class":41,"line":618},[39,918,403],{"class":105},[39,920,406],{"class":109},[39,922,924],{"class":41,"line":923},32,[39,925,443],{"class":109},[39,927,929],{"class":41,"line":928},33,[39,930,318],{"class":109},[39,932,934],{"class":41,"line":933},34,[39,935,324],{"class":109},[22,937,939],{"id":938},"fan-in-merging-multiple-channels","Fan-In — Merging Multiple Channels",[27,941,942,1411,1415],{"language":29},[31,943,945],{"className":33,"code":944,"language":29,"meta":35,"style":35},"\u002F\u002F Fan-in: merge multiple input channels into one output.\n\u002F\u002F Each input channel gets a goroutine that forwards to the output.\n\nfunc fanIn[T any](ctx context.Context, channels ...\u003C-chan T) \u003C-chan T {\n    out := make(chan T)\n    var wg sync.WaitGroup\n\n    for _, ch := range channels {\n        wg.Add(1)\n        go func() {\n            defer wg.Done()\n            for v := range ch {\n                select {\n                case out \u003C- v:\n                case \u003C-ctx.Done():\n                    return  \u002F\u002F cancelled — stop forwarding\n                }\n            }\n        }()\n    }\n\n    \u002F\u002F Close out after all forwarders finish\n    go func() {\n        wg.Wait()\n        close(out)\n    }()\n\n    return out\n}\n\n\u002F\u002F Usage:\nfunc main() {\n    ctx, cancel := context.WithCancel(context.Background())\n    defer cancel()\n\n    ch1 := generate(ctx, 1, 2, 3)\n    ch2 := generate(ctx, 4, 5, 6)\n    ch3 := generate(ctx, 7, 8, 9)\n\n    merged := fanIn(ctx, ch1, ch2, ch3)\n    for v := range merged {\n        fmt.Println(v)  \u002F\u002F 1-9 in some order (concurrent)\n    }\n}\n",[17,946,947,952,957,961,1008,1025,1041,1045,1060,1074,1084,1096,1110,1117,1130,1142,1150,1155,1159,1164,1168,1172,1177,1186,1195,1203,1208,1212,1220,1224,1228,1233,1242,1264,1273,1278,1304,1329,1356,1361,1374,1388,1401,1406],{"__ignoreMap":35},[39,948,949],{"class":41,"line":42},[39,950,951],{"class":45},"\u002F\u002F Fan-in: merge multiple input channels into one output.\n",[39,953,954],{"class":41,"line":49},[39,955,956],{"class":45},"\u002F\u002F Each input channel gets a goroutine that forwards to the output.\n",[39,958,959],{"class":41,"line":55},[39,960,95],{"emptyLinePlaceholder":94},[39,962,963,965,968,971,974,977,980,982,984,986,988,990,993,996,999,1001,1004,1006],{"class":41,"line":61},[39,964,102],{"class":101},[39,966,967],{"class":105}," fanIn",[39,969,970],{"class":109},"[",[39,972,973],{"class":361},"T",[39,975,976],{"class":105}," any",[39,978,979],{"class":109},"](",[39,981,658],{"class":361},[39,983,661],{"class":105},[39,985,664],{"class":109},[39,987,667],{"class":105},[39,989,134],{"class":109},[39,991,992],{"class":361},"channels",[39,994,995],{"class":101}," ...\u003C-chan",[39,997,998],{"class":105}," T",[39,1000,688],{"class":109},[39,1002,1003],{"class":101},"\u003C-chan",[39,1005,998],{"class":105},[39,1007,188],{"class":109},[39,1009,1010,1013,1015,1017,1019,1021,1023],{"class":41,"line":67},[39,1011,1012],{"class":109},"    out ",[39,1014,119],{"class":101},[39,1016,122],{"class":105},[39,1018,125],{"class":109},[39,1020,128],{"class":101},[39,1022,998],{"class":105},[39,1024,141],{"class":109},[39,1026,1027,1030,1033,1036,1038],{"class":41,"line":73},[39,1028,1029],{"class":101},"    var",[39,1031,1032],{"class":109}," wg ",[39,1034,1035],{"class":105},"sync",[39,1037,664],{"class":109},[39,1039,1040],{"class":105},"WaitGroup\n",[39,1042,1043],{"class":41,"line":79},[39,1044,95],{"emptyLinePlaceholder":94},[39,1046,1047,1049,1052,1054,1057],{"class":41,"line":85},[39,1048,375],{"class":101},[39,1050,1051],{"class":109}," _, ch ",[39,1053,119],{"class":101},[39,1055,1056],{"class":101}," range",[39,1058,1059],{"class":109}," channels {\n",[39,1061,1062,1065,1068,1070,1072],{"class":41,"line":91},[39,1063,1064],{"class":109},"        wg.",[39,1066,1067],{"class":105},"Add",[39,1069,125],{"class":109},[39,1071,138],{"class":137},[39,1073,141],{"class":109},[39,1075,1076,1079,1082],{"class":41,"line":98},[39,1077,1078],{"class":101},"        go",[39,1080,1081],{"class":101}," func",[39,1083,110],{"class":109},[39,1085,1086,1089,1092,1094],{"class":41,"line":113},[39,1087,1088],{"class":101},"            defer",[39,1090,1091],{"class":109}," wg.",[39,1093,780],{"class":105},[39,1095,523],{"class":109},[39,1097,1098,1101,1103,1105,1107],{"class":41,"line":144},[39,1099,1100],{"class":101},"            for",[39,1102,197],{"class":109},[39,1104,119],{"class":101},[39,1106,1056],{"class":101},[39,1108,1109],{"class":109}," ch {\n",[39,1111,1112,1115],{"class":41,"line":166},[39,1113,1114],{"class":101},"                select",[39,1116,188],{"class":109},[39,1118,1119,1122,1125,1127],{"class":41,"line":177},[39,1120,1121],{"class":101},"                case",[39,1123,1124],{"class":109}," out ",[39,1126,171],{"class":101},[39,1128,1129],{"class":109}," v:\n",[39,1131,1132,1134,1136,1138,1140],{"class":41,"line":182},[39,1133,1121],{"class":101},[39,1135,202],{"class":101},[39,1137,777],{"class":109},[39,1139,780],{"class":105},[39,1141,783],{"class":109},[39,1143,1144,1147],{"class":41,"line":191},[39,1145,1146],{"class":101},"                    return",[39,1148,1149],{"class":45},"  \u002F\u002F cancelled — stop forwarding\n",[39,1151,1152],{"class":41,"line":208},[39,1153,1154],{"class":109},"                }\n",[39,1156,1157],{"class":41,"line":226},[39,1158,745],{"class":109},[39,1160,1161],{"class":41,"line":240},[39,1162,1163],{"class":109},"        }()\n",[39,1165,1166],{"class":41,"line":254},[39,1167,318],{"class":109},[39,1169,1170],{"class":41,"line":278},[39,1171,95],{"emptyLinePlaceholder":94},[39,1173,1174],{"class":41,"line":292},[39,1175,1176],{"class":45},"    \u002F\u002F Close out after all forwarders finish\n",[39,1178,1179,1182,1184],{"class":41,"line":301},[39,1180,1181],{"class":101},"    go",[39,1183,1081],{"class":101},[39,1185,110],{"class":109},[39,1187,1188,1190,1193],{"class":41,"line":315},[39,1189,1064],{"class":109},[39,1191,1192],{"class":105},"Wait",[39,1194,523],{"class":109},[39,1196,1197,1200],{"class":41,"line":321},[39,1198,1199],{"class":105},"        close",[39,1201,1202],{"class":109},"(out)\n",[39,1204,1205],{"class":41,"line":580},[39,1206,1207],{"class":109},"    }()\n",[39,1209,1210],{"class":41,"line":590},[39,1211,95],{"emptyLinePlaceholder":94},[39,1213,1214,1217],{"class":41,"line":603},[39,1215,1216],{"class":101},"    return",[39,1218,1219],{"class":109}," out\n",[39,1221,1222],{"class":41,"line":608},[39,1223,324],{"class":109},[39,1225,1226],{"class":41,"line":613},[39,1227,95],{"emptyLinePlaceholder":94},[39,1229,1230],{"class":41,"line":618},[39,1231,1232],{"class":45},"\u002F\u002F Usage:\n",[39,1234,1235,1237,1240],{"class":41,"line":923},[39,1236,102],{"class":101},[39,1238,1239],{"class":105}," main",[39,1241,110],{"class":109},[39,1243,1244,1247,1249,1252,1255,1258,1261],{"class":41,"line":928},[39,1245,1246],{"class":109},"    ctx, cancel ",[39,1248,119],{"class":101},[39,1250,1251],{"class":109}," context.",[39,1253,1254],{"class":105},"WithCancel",[39,1256,1257],{"class":109},"(context.",[39,1259,1260],{"class":105},"Background",[39,1262,1263],{"class":109},"())\n",[39,1265,1266,1268,1271],{"class":41,"line":933},[39,1267,514],{"class":101},[39,1269,1270],{"class":105}," cancel",[39,1272,523],{"class":109},[39,1274,1276],{"class":41,"line":1275},35,[39,1277,95],{"emptyLinePlaceholder":94},[39,1279,1281,1283,1285,1288,1291,1293,1295,1297,1299,1302],{"class":41,"line":1280},36,[39,1282,116],{"class":109},[39,1284,119],{"class":101},[39,1286,1287],{"class":105}," generate",[39,1289,1290],{"class":109},"(ctx, ",[39,1292,138],{"class":137},[39,1294,134],{"class":109},[39,1296,421],{"class":137},[39,1298,134],{"class":109},[39,1300,1301],{"class":137},"3",[39,1303,141],{"class":109},[39,1305,1307,1309,1311,1313,1315,1318,1320,1322,1324,1327],{"class":41,"line":1306},37,[39,1308,147],{"class":109},[39,1310,119],{"class":101},[39,1312,1287],{"class":105},[39,1314,1290],{"class":109},[39,1316,1317],{"class":137},"4",[39,1319,134],{"class":109},[39,1321,269],{"class":137},[39,1323,134],{"class":109},[39,1325,1326],{"class":137},"6",[39,1328,141],{"class":109},[39,1330,1332,1335,1337,1339,1341,1344,1346,1349,1351,1354],{"class":41,"line":1331},38,[39,1333,1334],{"class":109},"    ch3 ",[39,1336,119],{"class":101},[39,1338,1287],{"class":105},[39,1340,1290],{"class":109},[39,1342,1343],{"class":137},"7",[39,1345,134],{"class":109},[39,1347,1348],{"class":137},"8",[39,1350,134],{"class":109},[39,1352,1353],{"class":137},"9",[39,1355,141],{"class":109},[39,1357,1359],{"class":41,"line":1358},39,[39,1360,95],{"emptyLinePlaceholder":94},[39,1362,1364,1367,1369,1371],{"class":41,"line":1363},40,[39,1365,1366],{"class":109},"    merged ",[39,1368,119],{"class":101},[39,1370,967],{"class":105},[39,1372,1373],{"class":109},"(ctx, ch1, ch2, ch3)\n",[39,1375,1377,1379,1381,1383,1385],{"class":41,"line":1376},41,[39,1378,375],{"class":101},[39,1380,197],{"class":109},[39,1382,119],{"class":101},[39,1384,1056],{"class":101},[39,1386,1387],{"class":109}," merged {\n",[39,1389,1391,1393,1395,1398],{"class":41,"line":1390},42,[39,1392,211],{"class":109},[39,1394,214],{"class":105},[39,1396,1397],{"class":109},"(v)  ",[39,1399,1400],{"class":45},"\u002F\u002F 1-9 in some order (concurrent)\n",[39,1402,1404],{"class":41,"line":1403},43,[39,1405,318],{"class":109},[39,1407,1409],{"class":41,"line":1408},44,[39,1410,324],{"class":109},[22,1412,1414],{"id":1413},"fan-out-distributing-work","Fan-Out — Distributing Work",[27,1416,1417,1689,1693],{"language":29},[31,1418,1420],{"className":33,"code":1419,"language":29,"meta":35,"style":35},"\u002F\u002F Fan-out: distribute work from one channel to multiple workers.\n\u002F\u002F Workers run concurrently, each processing jobs from the shared channel.\n\nfunc fanOut(ctx context.Context, jobs \u003C-chan Job, numWorkers int) \u003C-chan Result {\n    results := make(chan Result)\n    var wg sync.WaitGroup\n\n    for i := 0; i \u003C numWorkers; i++ {\n        wg.Add(1)\n        go func(id int) {\n            defer wg.Done()\n            for job := range jobs {\n                select {\n                case results \u003C- process(ctx, job):\n                case \u003C-ctx.Done():\n                    return\n                }\n            }\n        }(i)\n    }\n\n    go func() {\n        wg.Wait()\n        close(results)\n    }()\n\n    return results\n}\n",[17,1421,1422,1427,1432,1436,1479,1496,1508,1512,1538,1550,1565,1575,1589,1595,1609,1621,1626,1630,1634,1639,1643,1647,1655,1663,1670,1674,1678,1685],{"__ignoreMap":35},[39,1423,1424],{"class":41,"line":42},[39,1425,1426],{"class":45},"\u002F\u002F Fan-out: distribute work from one channel to multiple workers.\n",[39,1428,1429],{"class":41,"line":49},[39,1430,1431],{"class":45},"\u002F\u002F Workers run concurrently, each processing jobs from the shared channel.\n",[39,1433,1434],{"class":41,"line":55},[39,1435,95],{"emptyLinePlaceholder":94},[39,1437,1438,1440,1443,1445,1447,1449,1451,1453,1455,1458,1460,1463,1465,1468,1470,1472,1474,1477],{"class":41,"line":61},[39,1439,102],{"class":101},[39,1441,1442],{"class":105}," fanOut",[39,1444,125],{"class":109},[39,1446,658],{"class":361},[39,1448,661],{"class":105},[39,1450,664],{"class":109},[39,1452,667],{"class":105},[39,1454,134],{"class":109},[39,1456,1457],{"class":361},"jobs",[39,1459,365],{"class":101},[39,1461,1462],{"class":105}," Job",[39,1464,134],{"class":109},[39,1466,1467],{"class":361},"numWorkers",[39,1469,131],{"class":101},[39,1471,688],{"class":109},[39,1473,1003],{"class":101},[39,1475,1476],{"class":105}," Result",[39,1478,188],{"class":109},[39,1480,1481,1484,1486,1488,1490,1492,1494],{"class":41,"line":67},[39,1482,1483],{"class":109},"    results ",[39,1485,119],{"class":101},[39,1487,122],{"class":105},[39,1489,125],{"class":109},[39,1491,128],{"class":101},[39,1493,1476],{"class":105},[39,1495,141],{"class":109},[39,1497,1498,1500,1502,1504,1506],{"class":41,"line":73},[39,1499,1029],{"class":101},[39,1501,1032],{"class":109},[39,1503,1035],{"class":105},[39,1505,664],{"class":109},[39,1507,1040],{"class":105},[39,1509,1510],{"class":41,"line":79},[39,1511,95],{"emptyLinePlaceholder":94},[39,1513,1514,1516,1519,1521,1524,1527,1530,1533,1536],{"class":41,"line":85},[39,1515,375],{"class":101},[39,1517,1518],{"class":109}," i ",[39,1520,119],{"class":101},[39,1522,1523],{"class":137}," 0",[39,1525,1526],{"class":109},"; i ",[39,1528,1529],{"class":101},"\u003C",[39,1531,1532],{"class":109}," numWorkers; i",[39,1534,1535],{"class":101},"++",[39,1537,188],{"class":109},[39,1539,1540,1542,1544,1546,1548],{"class":41,"line":91},[39,1541,1064],{"class":109},[39,1543,1067],{"class":105},[39,1545,125],{"class":109},[39,1547,138],{"class":137},[39,1549,141],{"class":109},[39,1551,1552,1554,1556,1558,1561,1563],{"class":41,"line":98},[39,1553,1078],{"class":101},[39,1555,1081],{"class":101},[39,1557,125],{"class":109},[39,1559,1560],{"class":361},"id",[39,1562,131],{"class":101},[39,1564,370],{"class":109},[39,1566,1567,1569,1571,1573],{"class":41,"line":113},[39,1568,1088],{"class":101},[39,1570,1091],{"class":109},[39,1572,780],{"class":105},[39,1574,523],{"class":109},[39,1576,1577,1579,1582,1584,1586],{"class":41,"line":144},[39,1578,1100],{"class":101},[39,1580,1581],{"class":109}," job ",[39,1583,119],{"class":101},[39,1585,1056],{"class":101},[39,1587,1588],{"class":109}," jobs {\n",[39,1590,1591,1593],{"class":41,"line":166},[39,1592,1114],{"class":101},[39,1594,188],{"class":109},[39,1596,1597,1599,1602,1604,1606],{"class":41,"line":177},[39,1598,1121],{"class":101},[39,1600,1601],{"class":109}," results ",[39,1603,171],{"class":101},[39,1605,765],{"class":105},[39,1607,1608],{"class":109},"(ctx, job):\n",[39,1610,1611,1613,1615,1617,1619],{"class":41,"line":182},[39,1612,1121],{"class":101},[39,1614,202],{"class":101},[39,1616,777],{"class":109},[39,1618,780],{"class":105},[39,1620,783],{"class":109},[39,1622,1623],{"class":41,"line":191},[39,1624,1625],{"class":101},"                    return\n",[39,1627,1628],{"class":41,"line":208},[39,1629,1154],{"class":109},[39,1631,1632],{"class":41,"line":226},[39,1633,745],{"class":109},[39,1635,1636],{"class":41,"line":240},[39,1637,1638],{"class":109},"        }(i)\n",[39,1640,1641],{"class":41,"line":254},[39,1642,318],{"class":109},[39,1644,1645],{"class":41,"line":278},[39,1646,95],{"emptyLinePlaceholder":94},[39,1648,1649,1651,1653],{"class":41,"line":292},[39,1650,1181],{"class":101},[39,1652,1081],{"class":101},[39,1654,110],{"class":109},[39,1656,1657,1659,1661],{"class":41,"line":301},[39,1658,1064],{"class":109},[39,1660,1192],{"class":105},[39,1662,523],{"class":109},[39,1664,1665,1667],{"class":41,"line":315},[39,1666,1199],{"class":105},[39,1668,1669],{"class":109},"(results)\n",[39,1671,1672],{"class":41,"line":321},[39,1673,1207],{"class":109},[39,1675,1676],{"class":41,"line":580},[39,1677,95],{"emptyLinePlaceholder":94},[39,1679,1680,1682],{"class":41,"line":590},[39,1681,1216],{"class":101},[39,1683,1684],{"class":109}," results\n",[39,1686,1687],{"class":41,"line":603},[39,1688,324],{"class":109},[22,1690,1692],{"id":1691},"priority-select-the-nested-pattern","Priority Select — The Nested Pattern",[27,1694,1695,1888,1892],{"language":29},[31,1696,1698],{"className":33,"code":1697,"language":29,"meta":35,"style":35},"\u002F\u002F select picks randomly among ready cases — no priority.\n\u002F\u002F For priority, use a nested select: try the priority case first\n\u002F\u002F (non-blocking), then fall back to a regular select.\n\nfunc prioritySelect(high, low \u003C-chan int) {\n    for {\n        \u002F\u002F First, non-blocking check on high-priority channel:\n        select {\n        case v := \u003C-high:\n            fmt.Println(\"HIGH:\", v)\n            continue\n        default:\n        }\n\n        \u002F\u002F Then, regular select on both:\n        select {\n        case v := \u003C-high:\n            fmt.Println(\"HIGH:\", v)\n        case v := \u003C-low:\n            fmt.Println(\"LOW:\", v)\n        }\n    }\n}\n\u002F\u002F This drains high before processing low. But ⚠️ if high is always\n\u002F\u002F ready, low starves — use a separate goroutine or time-based fairness.\n",[17,1699,1700,1705,1710,1715,1719,1742,1748,1753,1759,1772,1785,1790,1797,1801,1805,1810,1816,1828,1840,1853,1866,1870,1874,1878,1883],{"__ignoreMap":35},[39,1701,1702],{"class":41,"line":42},[39,1703,1704],{"class":45},"\u002F\u002F select picks randomly among ready cases — no priority.\n",[39,1706,1707],{"class":41,"line":49},[39,1708,1709],{"class":45},"\u002F\u002F For priority, use a nested select: try the priority case first\n",[39,1711,1712],{"class":41,"line":55},[39,1713,1714],{"class":45},"\u002F\u002F (non-blocking), then fall back to a regular select.\n",[39,1716,1717],{"class":41,"line":61},[39,1718,95],{"emptyLinePlaceholder":94},[39,1720,1721,1723,1726,1728,1731,1733,1736,1738,1740],{"class":41,"line":67},[39,1722,102],{"class":101},[39,1724,1725],{"class":105}," prioritySelect",[39,1727,125],{"class":109},[39,1729,1730],{"class":361},"high",[39,1732,134],{"class":109},[39,1734,1735],{"class":361},"low",[39,1737,365],{"class":101},[39,1739,131],{"class":101},[39,1741,370],{"class":109},[39,1743,1744,1746],{"class":41,"line":73},[39,1745,375],{"class":101},[39,1747,188],{"class":109},[39,1749,1750],{"class":41,"line":79},[39,1751,1752],{"class":45},"        \u002F\u002F First, non-blocking check on high-priority channel:\n",[39,1754,1755,1757],{"class":41,"line":85},[39,1756,382],{"class":101},[39,1758,188],{"class":109},[39,1760,1761,1763,1765,1767,1769],{"class":41,"line":91},[39,1762,389],{"class":101},[39,1764,197],{"class":109},[39,1766,119],{"class":101},[39,1768,202],{"class":101},[39,1770,1771],{"class":109},"high:\n",[39,1773,1774,1776,1778,1780,1783],{"class":41,"line":98},[39,1775,430],{"class":109},[39,1777,214],{"class":105},[39,1779,125],{"class":109},[39,1781,1782],{"class":219},"\"HIGH:\"",[39,1784,223],{"class":109},[39,1786,1787],{"class":41,"line":113},[39,1788,1789],{"class":101},"            continue\n",[39,1791,1792,1795],{"class":41,"line":144},[39,1793,1794],{"class":101},"        default",[39,1796,298],{"class":109},[39,1798,1799],{"class":41,"line":166},[39,1800,443],{"class":109},[39,1802,1803],{"class":41,"line":177},[39,1804,95],{"emptyLinePlaceholder":94},[39,1806,1807],{"class":41,"line":182},[39,1808,1809],{"class":45},"        \u002F\u002F Then, regular select on both:\n",[39,1811,1812,1814],{"class":41,"line":191},[39,1813,382],{"class":101},[39,1815,188],{"class":109},[39,1817,1818,1820,1822,1824,1826],{"class":41,"line":208},[39,1819,389],{"class":101},[39,1821,197],{"class":109},[39,1823,119],{"class":101},[39,1825,202],{"class":101},[39,1827,1771],{"class":109},[39,1829,1830,1832,1834,1836,1838],{"class":41,"line":226},[39,1831,430],{"class":109},[39,1833,214],{"class":105},[39,1835,125],{"class":109},[39,1837,1782],{"class":219},[39,1839,223],{"class":109},[39,1841,1842,1844,1846,1848,1850],{"class":41,"line":240},[39,1843,389],{"class":101},[39,1845,197],{"class":109},[39,1847,119],{"class":101},[39,1849,202],{"class":101},[39,1851,1852],{"class":109},"low:\n",[39,1854,1855,1857,1859,1861,1864],{"class":41,"line":254},[39,1856,430],{"class":109},[39,1858,214],{"class":105},[39,1860,125],{"class":109},[39,1862,1863],{"class":219},"\"LOW:\"",[39,1865,223],{"class":109},[39,1867,1868],{"class":41,"line":278},[39,1869,443],{"class":109},[39,1871,1872],{"class":41,"line":292},[39,1873,318],{"class":109},[39,1875,1876],{"class":41,"line":301},[39,1877,324],{"class":109},[39,1879,1880],{"class":41,"line":315},[39,1881,1882],{"class":45},"\u002F\u002F This drains high before processing low. But ⚠️ if high is always\n",[39,1884,1885],{"class":41,"line":321},[39,1886,1887],{"class":45},"\u002F\u002F ready, low starves — use a separate goroutine or time-based fairness.\n",[22,1889,1891],{"id":1890},"the-done-channel-pattern-pre-context","The Done Channel Pattern (Pre-Context)",[27,1893,1894,2164,2171],{"language":29},[31,1895,1897],{"className":33,"code":1896,"language":29,"meta":35,"style":35},"\u002F\u002F Before context.Context, the done channel was the standard cancellation pattern.\n\u002F\u002F context generalizes this — but the pattern is still useful to understand.\n\nfunc workerDone(input \u003C-chan int, done \u003C-chan struct{}) {\n    for {\n        select {\n        case v, ok := \u003C-input:\n            if !ok {\n                return\n            }\n            process(v)\n        case \u003C-done:\n            return  \u002F\u002F cancellation signal — close(done) to broadcast\n        }\n    }\n}\n\n\u002F\u002F ✅ Prefer context.Context (which wraps this pattern):\nfunc workerCtx(ctx context.Context, input \u003C-chan int) error {\n    for {\n        select {\n        case v, ok := \u003C-input:\n            if !ok {\n                return nil\n            }\n            if err := process(ctx, v); err != nil {\n                return err\n            }\n        case \u003C-ctx.Done():\n            return ctx.Err()\n        }\n    }\n}\n",[17,1898,1899,1904,1909,1913,1941,1947,1953,1965,1973,1978,1982,1988,1996,2003,2007,2011,2015,2019,2024,2055,2061,2067,2079,2087,2094,2098,2119,2126,2130,2142,2152,2156,2160],{"__ignoreMap":35},[39,1900,1901],{"class":41,"line":42},[39,1902,1903],{"class":45},"\u002F\u002F Before context.Context, the done channel was the standard cancellation pattern.\n",[39,1905,1906],{"class":41,"line":49},[39,1907,1908],{"class":45},"\u002F\u002F context generalizes this — but the pattern is still useful to understand.\n",[39,1910,1911],{"class":41,"line":55},[39,1912,95],{"emptyLinePlaceholder":94},[39,1914,1915,1917,1920,1922,1924,1926,1928,1930,1933,1935,1938],{"class":41,"line":61},[39,1916,102],{"class":101},[39,1918,1919],{"class":105}," workerDone",[39,1921,125],{"class":109},[39,1923,362],{"class":361},[39,1925,365],{"class":101},[39,1927,131],{"class":101},[39,1929,134],{"class":109},[39,1931,1932],{"class":361},"done",[39,1934,365],{"class":101},[39,1936,1937],{"class":101}," struct",[39,1939,1940],{"class":109},"{}) {\n",[39,1942,1943,1945],{"class":41,"line":67},[39,1944,375],{"class":101},[39,1946,188],{"class":109},[39,1948,1949,1951],{"class":41,"line":73},[39,1950,382],{"class":101},[39,1952,188],{"class":109},[39,1954,1955,1957,1959,1961,1963],{"class":41,"line":79},[39,1956,389],{"class":101},[39,1958,712],{"class":109},[39,1960,119],{"class":101},[39,1962,202],{"class":101},[39,1964,398],{"class":109},[39,1966,1967,1969,1971],{"class":41,"line":85},[39,1968,723],{"class":101},[39,1970,726],{"class":101},[39,1972,729],{"class":109},[39,1974,1975],{"class":41,"line":91},[39,1976,1977],{"class":101},"                return\n",[39,1979,1980],{"class":41,"line":98},[39,1981,745],{"class":109},[39,1983,1984,1986],{"class":41,"line":113},[39,1985,403],{"class":105},[39,1987,406],{"class":109},[39,1989,1990,1992,1994],{"class":41,"line":144},[39,1991,389],{"class":101},[39,1993,202],{"class":101},[39,1995,890],{"class":109},[39,1997,1998,2000],{"class":41,"line":166},[39,1999,820],{"class":101},[39,2001,2002],{"class":45},"  \u002F\u002F cancellation signal — close(done) to broadcast\n",[39,2004,2005],{"class":41,"line":177},[39,2006,443],{"class":109},[39,2008,2009],{"class":41,"line":182},[39,2010,318],{"class":109},[39,2012,2013],{"class":41,"line":191},[39,2014,324],{"class":109},[39,2016,2017],{"class":41,"line":208},[39,2018,95],{"emptyLinePlaceholder":94},[39,2020,2021],{"class":41,"line":226},[39,2022,2023],{"class":45},"\u002F\u002F ✅ Prefer context.Context (which wraps this pattern):\n",[39,2025,2026,2028,2031,2033,2035,2037,2039,2041,2043,2045,2047,2049,2051,2053],{"class":41,"line":240},[39,2027,102],{"class":101},[39,2029,2030],{"class":105}," workerCtx",[39,2032,125],{"class":109},[39,2034,658],{"class":361},[39,2036,661],{"class":105},[39,2038,664],{"class":109},[39,2040,667],{"class":105},[39,2042,134],{"class":109},[39,2044,362],{"class":361},[39,2046,365],{"class":101},[39,2048,131],{"class":101},[39,2050,688],{"class":109},[39,2052,691],{"class":101},[39,2054,188],{"class":109},[39,2056,2057,2059],{"class":41,"line":254},[39,2058,375],{"class":101},[39,2060,188],{"class":109},[39,2062,2063,2065],{"class":41,"line":278},[39,2064,382],{"class":101},[39,2066,188],{"class":109},[39,2068,2069,2071,2073,2075,2077],{"class":41,"line":292},[39,2070,389],{"class":101},[39,2072,712],{"class":109},[39,2074,119],{"class":101},[39,2076,202],{"class":101},[39,2078,398],{"class":109},[39,2080,2081,2083,2085],{"class":41,"line":301},[39,2082,723],{"class":101},[39,2084,726],{"class":101},[39,2086,729],{"class":109},[39,2088,2089,2091],{"class":41,"line":315},[39,2090,734],{"class":101},[39,2092,2093],{"class":137}," nil\n",[39,2095,2096],{"class":41,"line":321},[39,2097,745],{"class":109},[39,2099,2100,2102,2105,2107,2109,2112,2115,2117],{"class":41,"line":580},[39,2101,723],{"class":101},[39,2103,2104],{"class":109}," err ",[39,2106,119],{"class":101},[39,2108,765],{"class":105},[39,2110,2111],{"class":109},"(ctx, v); err ",[39,2113,2114],{"class":101},"!=",[39,2116,737],{"class":137},[39,2118,188],{"class":109},[39,2120,2121,2123],{"class":41,"line":590},[39,2122,734],{"class":101},[39,2124,2125],{"class":109}," err\n",[39,2127,2128],{"class":41,"line":603},[39,2129,745],{"class":109},[39,2131,2132,2134,2136,2138,2140],{"class":41,"line":608},[39,2133,389],{"class":101},[39,2135,202],{"class":101},[39,2137,777],{"class":109},[39,2139,780],{"class":105},[39,2141,783],{"class":109},[39,2143,2144,2146,2148,2150],{"class":41,"line":613},[39,2145,820],{"class":101},[39,2147,790],{"class":109},[39,2149,793],{"class":105},[39,2151,523],{"class":109},[39,2153,2154],{"class":41,"line":618},[39,2155,443],{"class":109},[39,2157,2158],{"class":41,"line":923},[39,2159,318],{"class":109},[39,2161,2162],{"class":41,"line":928},[39,2163,324],{"class":109},[22,2165,2167,2168],{"id":2166},"non-blocking-operations-with-default","Non-Blocking Operations with ",[17,2169,2170],{},"default",[27,2172,2173,2381,2385],{"language":29},[31,2174,2176],{"className":33,"code":2175,"language":29,"meta":35,"style":35},"\u002F\u002F default makes select non-blocking — runs default if no case is ready.\n\nfunc nonBlocking(input \u003C-chan int) {\n    select {\n    case v := \u003C-input:\n        fmt.Println(\"got:\", v)\n    default:\n        fmt.Println(\"no value ready\")\n    }\n}\n\n\u002F\u002F ─── Drop pattern: send if room, drop if full ───\nfunc dropPattern(events chan\u003C- Event, e Event) {\n    select {\n    case events \u003C- e:  \u002F\u002F sent\n    default:\n        log.Printf(\"dropping event (queue full): %+v\", e)  \u002F\u002F drop\n    }\n}\n\u002F\u002F Use for metrics\u002Fevents where dropping under load is acceptable.\n\u002F\u002F Without default, a full channel blocks the producer → backpressure.\n\n\u002F\u002F ⚠️ Don't use default in a for-select loop — it causes a busy-spin (100% CPU).\n\u002F\u002F Only use default for one-shot non-blocking checks.\n",[17,2177,2178,2183,2187,2204,2210,2222,2235,2241,2254,2258,2262,2266,2271,2297,2303,2318,2324,2349,2353,2357,2362,2367,2371,2376],{"__ignoreMap":35},[39,2179,2180],{"class":41,"line":42},[39,2181,2182],{"class":45},"\u002F\u002F default makes select non-blocking — runs default if no case is ready.\n",[39,2184,2185],{"class":41,"line":49},[39,2186,95],{"emptyLinePlaceholder":94},[39,2188,2189,2191,2194,2196,2198,2200,2202],{"class":41,"line":55},[39,2190,102],{"class":101},[39,2192,2193],{"class":105}," nonBlocking",[39,2195,125],{"class":109},[39,2197,362],{"class":361},[39,2199,365],{"class":101},[39,2201,131],{"class":101},[39,2203,370],{"class":109},[39,2205,2206,2208],{"class":41,"line":61},[39,2207,185],{"class":101},[39,2209,188],{"class":109},[39,2211,2212,2214,2216,2218,2220],{"class":41,"line":67},[39,2213,194],{"class":101},[39,2215,197],{"class":109},[39,2217,119],{"class":101},[39,2219,202],{"class":101},[39,2221,398],{"class":109},[39,2223,2224,2226,2228,2230,2233],{"class":41,"line":73},[39,2225,211],{"class":109},[39,2227,214],{"class":105},[39,2229,125],{"class":109},[39,2231,2232],{"class":219},"\"got:\"",[39,2234,223],{"class":109},[39,2236,2237,2239],{"class":41,"line":79},[39,2238,295],{"class":101},[39,2240,298],{"class":109},[39,2242,2243,2245,2247,2249,2252],{"class":41,"line":85},[39,2244,211],{"class":109},[39,2246,214],{"class":105},[39,2248,125],{"class":109},[39,2250,2251],{"class":219},"\"no value ready\"",[39,2253,141],{"class":109},[39,2255,2256],{"class":41,"line":91},[39,2257,318],{"class":109},[39,2259,2260],{"class":41,"line":98},[39,2261,324],{"class":109},[39,2263,2264],{"class":41,"line":113},[39,2265,95],{"emptyLinePlaceholder":94},[39,2267,2268],{"class":41,"line":144},[39,2269,2270],{"class":45},"\u002F\u002F ─── Drop pattern: send if room, drop if full ───\n",[39,2272,2273,2275,2278,2280,2283,2285,2288,2290,2293,2295],{"class":41,"line":166},[39,2274,102],{"class":101},[39,2276,2277],{"class":105}," dropPattern",[39,2279,125],{"class":109},[39,2281,2282],{"class":361},"events",[39,2284,683],{"class":101},[39,2286,2287],{"class":105}," Event",[39,2289,134],{"class":109},[39,2291,2292],{"class":361},"e",[39,2294,2287],{"class":105},[39,2296,370],{"class":109},[39,2298,2299,2301],{"class":41,"line":177},[39,2300,185],{"class":101},[39,2302,188],{"class":109},[39,2304,2305,2307,2310,2312,2315],{"class":41,"line":182},[39,2306,194],{"class":101},[39,2308,2309],{"class":109}," events ",[39,2311,171],{"class":101},[39,2313,2314],{"class":109}," e:  ",[39,2316,2317],{"class":45},"\u002F\u002F sent\n",[39,2319,2320,2322],{"class":41,"line":191},[39,2321,295],{"class":101},[39,2323,298],{"class":109},[39,2325,2326,2329,2332,2334,2337,2340,2343,2346],{"class":41,"line":208},[39,2327,2328],{"class":109},"        log.",[39,2330,2331],{"class":105},"Printf",[39,2333,125],{"class":109},[39,2335,2336],{"class":219},"\"dropping event (queue full): ",[39,2338,2339],{"class":137},"%+v",[39,2341,2342],{"class":219},"\"",[39,2344,2345],{"class":109},", e)  ",[39,2347,2348],{"class":45},"\u002F\u002F drop\n",[39,2350,2351],{"class":41,"line":226},[39,2352,318],{"class":109},[39,2354,2355],{"class":41,"line":240},[39,2356,324],{"class":109},[39,2358,2359],{"class":41,"line":254},[39,2360,2361],{"class":45},"\u002F\u002F Use for metrics\u002Fevents where dropping under load is acceptable.\n",[39,2363,2364],{"class":41,"line":278},[39,2365,2366],{"class":45},"\u002F\u002F Without default, a full channel blocks the producer → backpressure.\n",[39,2368,2369],{"class":41,"line":292},[39,2370,95],{"emptyLinePlaceholder":94},[39,2372,2373],{"class":41,"line":301},[39,2374,2375],{"class":45},"\u002F\u002F ⚠️ Don't use default in a for-select loop — it causes a busy-spin (100% CPU).\n",[39,2377,2378],{"class":41,"line":315},[39,2379,2380],{"class":45},"\u002F\u002F Only use default for one-shot non-blocking checks.\n",[22,2382,2384],{"id":2383},"production-pattern-graceful-shutdown","Production Pattern — Graceful Shutdown",[27,2386,2387,2700,2704,2804,2808,2907,2911],{"language":29},[31,2388,2390],{"className":33,"code":2389,"language":29,"meta":35,"style":35},"func runServer(ctx context.Context, jobs \u003C-chan Job) error {\n    \u002F\u002F Process jobs until context is cancelled\n    for {\n        select {\n        case job, ok := \u003C-jobs:\n            if !ok {\n                return nil  \u002F\u002F jobs channel closed — clean exit\n            }\n            if err := process(ctx, job); err != nil {\n                return fmt.Errorf(\"process job %d: %w\", job.ID, err)\n            }\n        case \u003C-ctx.Done():\n            \u002F\u002F Drain in-flight jobs (optional), then exit\n            return ctx.Err()\n        }\n    }\n}\n\nfunc main() {\n    ctx, stop := signal.NotifyContext(context.Background(),\n        syscall.SIGINT, syscall.SIGTERM)\n    defer stop()\n\n    jobs := make(chan Job, 100)\n    \u002F\u002F ... start job producers ...\n\n    if err := runServer(ctx, jobs); err != nil &&\n        !errors.Is(err, context.Canceled) {\n        log.Fatal(err)\n    }\n}\n",[17,2391,2392,2423,2428,2434,2440,2454,2462,2471,2475,2494,2523,2527,2539,2544,2554,2558,2562,2566,2570,2578,2598,2603,2612,2616,2638,2643,2647,2668,2682,2692,2696],{"__ignoreMap":35},[39,2393,2394,2396,2399,2401,2403,2405,2407,2409,2411,2413,2415,2417,2419,2421],{"class":41,"line":42},[39,2395,102],{"class":101},[39,2397,2398],{"class":105}," runServer",[39,2400,125],{"class":109},[39,2402,658],{"class":361},[39,2404,661],{"class":105},[39,2406,664],{"class":109},[39,2408,667],{"class":105},[39,2410,134],{"class":109},[39,2412,1457],{"class":361},[39,2414,365],{"class":101},[39,2416,1462],{"class":105},[39,2418,688],{"class":109},[39,2420,691],{"class":101},[39,2422,188],{"class":109},[39,2424,2425],{"class":41,"line":49},[39,2426,2427],{"class":45},"    \u002F\u002F Process jobs until context is cancelled\n",[39,2429,2430,2432],{"class":41,"line":55},[39,2431,375],{"class":101},[39,2433,188],{"class":109},[39,2435,2436,2438],{"class":41,"line":61},[39,2437,382],{"class":101},[39,2439,188],{"class":109},[39,2441,2442,2444,2447,2449,2451],{"class":41,"line":67},[39,2443,389],{"class":101},[39,2445,2446],{"class":109}," job, ok ",[39,2448,119],{"class":101},[39,2450,202],{"class":101},[39,2452,2453],{"class":109},"jobs:\n",[39,2455,2456,2458,2460],{"class":41,"line":73},[39,2457,723],{"class":101},[39,2459,726],{"class":101},[39,2461,729],{"class":109},[39,2463,2464,2466,2468],{"class":41,"line":79},[39,2465,734],{"class":101},[39,2467,737],{"class":137},[39,2469,2470],{"class":45},"  \u002F\u002F jobs channel closed — clean exit\n",[39,2472,2473],{"class":41,"line":85},[39,2474,745],{"class":109},[39,2476,2477,2479,2481,2483,2485,2488,2490,2492],{"class":41,"line":91},[39,2478,723],{"class":101},[39,2480,2104],{"class":109},[39,2482,119],{"class":101},[39,2484,765],{"class":105},[39,2486,2487],{"class":109},"(ctx, job); err ",[39,2489,2114],{"class":101},[39,2491,737],{"class":137},[39,2493,188],{"class":109},[39,2495,2496,2498,2501,2504,2506,2509,2512,2515,2518,2520],{"class":41,"line":98},[39,2497,734],{"class":101},[39,2499,2500],{"class":109}," fmt.",[39,2502,2503],{"class":105},"Errorf",[39,2505,125],{"class":109},[39,2507,2508],{"class":219},"\"process job ",[39,2510,2511],{"class":137},"%d",[39,2513,2514],{"class":219},": ",[39,2516,2517],{"class":137},"%w",[39,2519,2342],{"class":219},[39,2521,2522],{"class":109},", job.ID, err)\n",[39,2524,2525],{"class":41,"line":113},[39,2526,745],{"class":109},[39,2528,2529,2531,2533,2535,2537],{"class":41,"line":144},[39,2530,389],{"class":101},[39,2532,202],{"class":101},[39,2534,777],{"class":109},[39,2536,780],{"class":105},[39,2538,783],{"class":109},[39,2540,2541],{"class":41,"line":166},[39,2542,2543],{"class":45},"            \u002F\u002F Drain in-flight jobs (optional), then exit\n",[39,2545,2546,2548,2550,2552],{"class":41,"line":177},[39,2547,820],{"class":101},[39,2549,790],{"class":109},[39,2551,793],{"class":105},[39,2553,523],{"class":109},[39,2555,2556],{"class":41,"line":182},[39,2557,443],{"class":109},[39,2559,2560],{"class":41,"line":191},[39,2561,318],{"class":109},[39,2563,2564],{"class":41,"line":208},[39,2565,324],{"class":109},[39,2567,2568],{"class":41,"line":226},[39,2569,95],{"emptyLinePlaceholder":94},[39,2571,2572,2574,2576],{"class":41,"line":240},[39,2573,102],{"class":101},[39,2575,1239],{"class":105},[39,2577,110],{"class":109},[39,2579,2580,2583,2585,2588,2591,2593,2595],{"class":41,"line":254},[39,2581,2582],{"class":109},"    ctx, stop ",[39,2584,119],{"class":101},[39,2586,2587],{"class":109}," signal.",[39,2589,2590],{"class":105},"NotifyContext",[39,2592,1257],{"class":109},[39,2594,1260],{"class":105},[39,2596,2597],{"class":109},"(),\n",[39,2599,2600],{"class":41,"line":278},[39,2601,2602],{"class":109},"        syscall.SIGINT, syscall.SIGTERM)\n",[39,2604,2605,2607,2610],{"class":41,"line":292},[39,2606,514],{"class":101},[39,2608,2609],{"class":105}," stop",[39,2611,523],{"class":109},[39,2613,2614],{"class":41,"line":301},[39,2615,95],{"emptyLinePlaceholder":94},[39,2617,2618,2621,2623,2625,2627,2629,2631,2633,2636],{"class":41,"line":315},[39,2619,2620],{"class":109},"    jobs ",[39,2622,119],{"class":101},[39,2624,122],{"class":105},[39,2626,125],{"class":109},[39,2628,128],{"class":101},[39,2630,1462],{"class":105},[39,2632,134],{"class":109},[39,2634,2635],{"class":137},"100",[39,2637,141],{"class":109},[39,2639,2640],{"class":41,"line":321},[39,2641,2642],{"class":45},"    \u002F\u002F ... start job producers ...\n",[39,2644,2645],{"class":41,"line":580},[39,2646,95],{"emptyLinePlaceholder":94},[39,2648,2649,2652,2654,2656,2658,2661,2663,2665],{"class":41,"line":590},[39,2650,2651],{"class":101},"    if",[39,2653,2104],{"class":109},[39,2655,119],{"class":101},[39,2657,2398],{"class":105},[39,2659,2660],{"class":109},"(ctx, jobs); err ",[39,2662,2114],{"class":101},[39,2664,737],{"class":137},[39,2666,2667],{"class":101}," &&\n",[39,2669,2670,2673,2676,2679],{"class":41,"line":603},[39,2671,2672],{"class":101},"        !",[39,2674,2675],{"class":109},"errors.",[39,2677,2678],{"class":105},"Is",[39,2680,2681],{"class":109},"(err, context.Canceled) {\n",[39,2683,2684,2686,2689],{"class":41,"line":608},[39,2685,2328],{"class":109},[39,2687,2688],{"class":105},"Fatal",[39,2690,2691],{"class":109},"(err)\n",[39,2693,2694],{"class":41,"line":613},[39,2695,318],{"class":109},[39,2697,2698],{"class":41,"line":618},[39,2699,324],{"class":109},[22,2701,2703],{"id":2702},"tips-tricks","💡 Tips & Tricks",[2705,2706,2707,2723,2740,2750,2764,2776],"ul",{},[2708,2709,2710,2714,2715,2718,2719,2722],"li",{},[2711,2712,2713],"strong",{},"Idiom",": use ",[17,2716,2717],{},"for { select { ... } }"," as the standard concurrent loop — always include a ",[17,2720,2721],{},"\u003C-ctx.Done()"," case so the goroutine can exit. A select loop without an exit path is a leak.",[2708,2724,2725,2714,2727,2730,2731,2733,2734,2736,2737,2739],{},[2711,2726,2713],{},[17,2728,2729],{},"time.NewTimer"," + ",[17,2732,520],{}," in tight loops, not ",[17,2735,331],{}," — ",[17,2738,331],{}," leaks the timer goroutine until it fires. In hot loops, this accumulates thousands of leaked timers.",[2708,2741,2742,2714,2744,2746,2747,2749],{},[2711,2743,2713],{},[17,2745,2170],{}," for non-blocking sends\u002Freceives — \"try to send, drop if full\" for metrics\u002Fevents where dropping under load is acceptable. Without ",[17,2748,2170],{},", a full channel blocks the producer.",[2708,2751,2752,2714,2754,2756,2757,2759,2760,2763],{},[2711,2753,2713],{},[17,2755,19],{}," with ",[17,2758,2721],{}," in every blocking wait — lets the goroutine exit even if the channel never produces. Without the done case, a blocked ",[17,2761,2762],{},"\u003C-ch"," can't be cancelled.",[2708,2765,2766,2768,2769,2772,2773,2775],{},[2711,2767,2713],{},": for priority among cases, use a nested select — first a non-blocking select on the priority channel (",[17,2770,2771],{},"case v := \u003C-priority: ...; default:","), then a regular select. Go's ",[17,2774,19],{}," is random, not prioritized.",[2708,2777,2778,2514,2781,2784,2785,2788,2789,2791,2792,2795,2796,2799,2800,2803],{},[2711,2779,2780],{},"Debug",[17,2782,2783],{},"break"," in a ",[17,2786,2787],{},"for-select"," only breaks the ",[17,2790,19],{},", not the ",[17,2793,2794],{},"for"," — use ",[17,2797,2798],{},"return"," or ",[17,2801,2802],{},"break loop"," (labeled) to exit the loop.",[22,2805,2807],{"id":2806},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[2705,2809,2810,2819,2830,2836,2851,2861,2870,2881,2901],{},[2708,2811,2812,2818],{},[2711,2813,2814,2817],{},[17,2815,2816],{},"select {}"," blocks forever",": no cases, no default — permanent block. Used to keep a goroutine alive, but a bug if unintended.",[2708,2820,2821,2829],{},[2711,2822,2823,2825,2826,2828],{},[17,2824,19],{}," with only ",[17,2827,2170],{}," runs the default and continues",": a no-op.",[2708,2831,2832,2835],{},[2711,2833,2834],{},"Random selection among ready cases",": no priority. Don't rely on case order.",[2708,2837,2838,2843,2844,2846,2847,2730,2849,664],{},[2711,2839,2840,2842],{},[17,2841,331],{}," leaks",": the timer's goroutine lingers until the duration elapses, even if the ",[17,2845,19],{}," took another case. In hot loops, use ",[17,2848,2729],{},[17,2850,520],{},[2708,2852,2853,2858,2859,664],{},[2711,2854,2855,2857],{},[17,2856,2170],{}," makes the select non-blocking",": if you want to block (wait for a case), omit ",[17,2860,2170],{},[2708,2862,2863,2514,2866,2869],{},[2711,2864,2865],{},"A nil channel case is never ready",[17,2867,2868],{},"select { case x := \u003C-nilch: ... }"," never fires. Useful for disabling cases, a footgun if unintended.",[2708,2871,2872,2877,2878,2880],{},[2711,2873,2874,2875],{},"Sending to a closed channel panics inside ",[17,2876,19],{},": same rule as outside — ",[17,2879,19],{}," doesn't protect against sends on closed channels.",[2708,2882,2883,2891,2892,2894,2895,2897,2898,2900],{},[2711,2884,2885,2756,2887,2788,2889],{},[17,2886,2787],{},[17,2888,2783],{},[17,2890,19],{},": the ",[17,2893,2794],{}," continues. Use ",[17,2896,2798],{}," or labeled ",[17,2899,2783],{}," to exit the loop.",[2708,2902,2903,2906],{},[2711,2904,2905],{},"Starvation",": if one case is always ready, another may never be picked (random helps, but isn't fair). Use separate goroutines or explicit scheduling.",[22,2908,2910],{"id":2909},"quick-quiz","🧠 Quick Quiz",[27,2912,2913,3025],{"language":29},[31,2914,2916],{"className":33,"code":2915,"language":29,"meta":35,"style":35},"func main() {\n    ch := make(chan int, 1)\n    ch \u003C- 1\n\n    select {\n    case v := \u003C-ch:\n        fmt.Println(\"received\", v)\n    case ch \u003C- 2:\n        fmt.Println(\"sent 2\")\n    }\n}\n",[17,2917,2918,2926,2947,2955,2959,2965,2977,2990,3004,3017,3021],{"__ignoreMap":35},[39,2919,2920,2922,2924],{"class":41,"line":42},[39,2921,102],{"class":101},[39,2923,1239],{"class":105},[39,2925,110],{"class":109},[39,2927,2928,2931,2933,2935,2937,2939,2941,2943,2945],{"class":41,"line":49},[39,2929,2930],{"class":109},"    ch ",[39,2932,119],{"class":101},[39,2934,122],{"class":105},[39,2936,125],{"class":109},[39,2938,128],{"class":101},[39,2940,131],{"class":101},[39,2942,134],{"class":109},[39,2944,138],{"class":137},[39,2946,141],{"class":109},[39,2948,2949,2951,2953],{"class":41,"line":55},[39,2950,2930],{"class":109},[39,2952,171],{"class":101},[39,2954,174],{"class":137},[39,2956,2957],{"class":41,"line":61},[39,2958,95],{"emptyLinePlaceholder":94},[39,2960,2961,2963],{"class":41,"line":67},[39,2962,185],{"class":101},[39,2964,188],{"class":109},[39,2966,2967,2969,2971,2973,2975],{"class":41,"line":73},[39,2968,194],{"class":101},[39,2970,197],{"class":109},[39,2972,119],{"class":101},[39,2974,202],{"class":101},[39,2976,914],{"class":109},[39,2978,2979,2981,2983,2985,2988],{"class":41,"line":79},[39,2980,211],{"class":109},[39,2982,214],{"class":105},[39,2984,125],{"class":109},[39,2986,2987],{"class":219},"\"received\"",[39,2989,223],{"class":109},[39,2991,2992,2994,2997,2999,3002],{"class":41,"line":85},[39,2993,194],{"class":101},[39,2995,2996],{"class":109}," ch ",[39,2998,171],{"class":101},[39,3000,3001],{"class":137}," 2",[39,3003,298],{"class":109},[39,3005,3006,3008,3010,3012,3015],{"class":41,"line":91},[39,3007,211],{"class":109},[39,3009,214],{"class":105},[39,3011,125],{"class":109},[39,3013,3014],{"class":219},"\"sent 2\"",[39,3016,141],{"class":109},[39,3018,3019],{"class":41,"line":98},[39,3020,318],{"class":109},[39,3022,3023],{"class":41,"line":113},[39,3024,324],{"class":109},[14,3026,3027],{},"Which case runs?",[3029,3030,3031,3035,3042,3050,3053,3067,3070,3080],"details",{},[3032,3033,3034],"summary",{},"Answer",[14,3036,3037,3038,3041],{},"The ",[2711,3039,3040],{},"receive case"," runs:",[31,3043,3048],{"className":3044,"code":3046,"language":3047},[3045],"language-text","received 1\n","text",[17,3049,3046],{"__ignoreMap":35},[14,3051,3052],{},"Both cases could be ready:",[2705,3054,3055,3061],{},[2708,3056,3057,3060],{},[17,3058,3059],{},"case v := \u003C-ch",": ready — there's a buffered value (1)",[2708,3062,3063,3066],{},[17,3064,3065],{},"case ch \u003C- 2",": NOT ready — the buffer is full (capacity 1, already has 1)",[14,3068,3069],{},"So only the receive case is ready. It runs, printing \"received 1\".",[14,3071,3072,3073,3075,3076,3079],{},"After the receive, the buffer is empty — but the ",[17,3074,19],{}," already chose. The ",[17,3077,3078],{},"ch \u003C- 2"," send case was not ready (buffer was full), so it was never considered.",[14,3081,3082,3083,3086,3087,3089],{},"If the buffer had capacity 2 (",[17,3084,3085],{},"make(chan int, 2)","), both cases would be ready, and ",[17,3088,19],{}," would pick one at random.",[22,3091,3093],{"id":3092},"whats-next","📚 What's Next",[14,3095,3096,3097,3102],{},"→ ",[3098,3099,3101],"a",{"href":3100},"\u002Fgo\u002F19-sync-package","19 — sync Package"," — Mutex, RWMutex, WaitGroup, Once, Cond, Pool, and Map — the lower-level synchronization primitives.",[3104,3105,3106],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":35,"searchDepth":49,"depth":49,"links":3108},[3109,3110,3112],{"id":24,"depth":49,"text":25},{"id":327,"depth":49,"text":3111},"Timeout — time.After and the Leak",{"id":3092,"depth":49,"text":3093},"Timeout patterns, the time.After leak, fan-in\u002Ffan-out, priority selects, for-select loops, and the nil-channel state machine pattern.","md",{},"\u002Fgo\u002F18-select-and-multiplexing",{"title":5,"description":3113},"go\u002F18-select-and-multiplexing","GN6pZ5VqIjRfx3kSQMyvD-tOIQ6XpOsXNiEgVK3LVBQ",1789924648592]