[{"data":1,"prerenderedAt":2682},["ShallowReactive",2],{"page-\u002Fgo\u002F17-channels":3},{"id":4,"title":5,"body":6,"description":2675,"extension":2676,"meta":2677,"navigation":141,"path":2678,"seo":2679,"stem":2680,"__hash__":2681},"content\u002Fgo\u002F17-channels.md","17 — Channels",{"type":7,"value":8,"toc":2670},"minimark",[9,13,18,2666],[10,11,5],"h1",{"id":12},"_17-channels",[14,15,17],"h2",{"id":16},"channel-semantics-the-complete-table","Channel Semantics — The Complete Table",[19,20,22,345,349,2592,2649,2653],"code-wrapper",{"language":21},"go",[23,24,28],"pre",{"className":25,"code":26,"language":21,"meta":27,"style":27},"language-go shiki shiki-themes github-light github-dark","\u002F\u002F ┌──────────────────────────────────────────────────────────────────────────┐\n\u002F\u002F │ Operation         │ State                │ Behavior                      │\n\u002F\u002F │ ──────────────────│ ─────────────────── │ ────────────────────────────── │\n\u002F\u002F │ Send (ch \u003C- v)    │ unbuffered, no rx    │ blocks until receiver ready   │\n\u002F\u002F │ Send              │ buffered, buffer full│ blocks until space available  │\n\u002F\u002F │ Send              │ closed               │ PANIC                         │\n\u002F\u002F │ Send              │ nil                  │ blocks forever                │\n\u002F\u002F │ Receive (v := \u003C-ch)│ unbuffered, no tx   │ blocks until sender ready      │\n\u002F\u002F │ Receive            │ buffered, empty     │ blocks until value available   │\n\u002F\u002F │ Receive            │ closed, drained      │ returns zero value, ok=false  │\n\u002F\u002F │ Receive            │ nil                  │ blocks forever                │\n\u002F\u002F │ close(ch)          │ open                 │ closes; receivers unblock     │\n\u002F\u002F │ close(ch)          │ closed               │ PANIC                         │\n\u002F\u002F │ close(ch)          │ nil                  │ PANIC                         │\n\u002F\u002F │ len(ch)             │ any                  │ # of buffered elements         │\n\u002F\u002F │ cap(ch)             │ any                  │ buffer capacity               │\n\u002F\u002F └──────────────────────────────────────────────────────────────────────────┘\n\nfunc basics() {\n    \u002F\u002F Unbuffered — synchronous rendezvous (send blocks until receive):\n    ch := make(chan int)\n    go func() { ch \u003C- 42 }()  \u002F\u002F blocks until someone receives\n    v := \u003C-ch                 \u002F\u002F receives 42, unblocks the sender\n    fmt.Println(v)            \u002F\u002F 42\n\n    \u002F\u002F Buffered — asynchronous up to capacity:\n    bch := make(chan int, 3)\n    bch \u003C- 1  \u002F\u002F doesn't block (buffer has space)\n    bch \u003C- 2\n    bch \u003C- 3\n    \u002F\u002F bch \u003C- 4  \u002F\u002F blocks (buffer full) until someone receives\n    fmt.Println(\u003C-bch)  \u002F\u002F 1 (FIFO)\n}\n","",[29,30,31,40,46,52,58,64,70,76,82,88,94,100,106,112,118,124,130,136,143,158,164,188,213,230,245,250,256,280,293,303,313,322,339],"code",{"__ignoreMap":27},[32,33,36],"span",{"class":34,"line":35},"line",1,[32,37,39],{"class":38},"sdCPZ","\u002F\u002F ┌──────────────────────────────────────────────────────────────────────────┐\n",[32,41,43],{"class":34,"line":42},2,[32,44,45],{"class":38},"\u002F\u002F │ Operation         │ State                │ Behavior                      │\n",[32,47,49],{"class":34,"line":48},3,[32,50,51],{"class":38},"\u002F\u002F │ ──────────────────│ ─────────────────── │ ────────────────────────────── │\n",[32,53,55],{"class":34,"line":54},4,[32,56,57],{"class":38},"\u002F\u002F │ Send (ch \u003C- v)    │ unbuffered, no rx    │ blocks until receiver ready   │\n",[32,59,61],{"class":34,"line":60},5,[32,62,63],{"class":38},"\u002F\u002F │ Send              │ buffered, buffer full│ blocks until space available  │\n",[32,65,67],{"class":34,"line":66},6,[32,68,69],{"class":38},"\u002F\u002F │ Send              │ closed               │ PANIC                         │\n",[32,71,73],{"class":34,"line":72},7,[32,74,75],{"class":38},"\u002F\u002F │ Send              │ nil                  │ blocks forever                │\n",[32,77,79],{"class":34,"line":78},8,[32,80,81],{"class":38},"\u002F\u002F │ Receive (v := \u003C-ch)│ unbuffered, no tx   │ blocks until sender ready      │\n",[32,83,85],{"class":34,"line":84},9,[32,86,87],{"class":38},"\u002F\u002F │ Receive            │ buffered, empty     │ blocks until value available   │\n",[32,89,91],{"class":34,"line":90},10,[32,92,93],{"class":38},"\u002F\u002F │ Receive            │ closed, drained      │ returns zero value, ok=false  │\n",[32,95,97],{"class":34,"line":96},11,[32,98,99],{"class":38},"\u002F\u002F │ Receive            │ nil                  │ blocks forever                │\n",[32,101,103],{"class":34,"line":102},12,[32,104,105],{"class":38},"\u002F\u002F │ close(ch)          │ open                 │ closes; receivers unblock     │\n",[32,107,109],{"class":34,"line":108},13,[32,110,111],{"class":38},"\u002F\u002F │ close(ch)          │ closed               │ PANIC                         │\n",[32,113,115],{"class":34,"line":114},14,[32,116,117],{"class":38},"\u002F\u002F │ close(ch)          │ nil                  │ PANIC                         │\n",[32,119,121],{"class":34,"line":120},15,[32,122,123],{"class":38},"\u002F\u002F │ len(ch)             │ any                  │ # of buffered elements         │\n",[32,125,127],{"class":34,"line":126},16,[32,128,129],{"class":38},"\u002F\u002F │ cap(ch)             │ any                  │ buffer capacity               │\n",[32,131,133],{"class":34,"line":132},17,[32,134,135],{"class":38},"\u002F\u002F └──────────────────────────────────────────────────────────────────────────┘\n",[32,137,139],{"class":34,"line":138},18,[32,140,142],{"emptyLinePlaceholder":141},true,"\n",[32,144,146,150,154],{"class":34,"line":145},19,[32,147,149],{"class":148},"svdQ7","func",[32,151,153],{"class":152},"sIsaT"," basics",[32,155,157],{"class":156},"ssxIu","() {\n",[32,159,161],{"class":34,"line":160},20,[32,162,163],{"class":38},"    \u002F\u002F Unbuffered — synchronous rendezvous (send blocks until receive):\n",[32,165,167,170,173,176,179,182,185],{"class":34,"line":166},21,[32,168,169],{"class":156},"    ch ",[32,171,172],{"class":148},":=",[32,174,175],{"class":152}," make",[32,177,178],{"class":156},"(",[32,180,181],{"class":148},"chan",[32,183,184],{"class":148}," int",[32,186,187],{"class":156},")\n",[32,189,191,194,197,200,203,207,210],{"class":34,"line":190},22,[32,192,193],{"class":148},"    go",[32,195,196],{"class":148}," func",[32,198,199],{"class":156},"() { ch ",[32,201,202],{"class":148},"\u003C-",[32,204,206],{"class":205},"snvgF"," 42",[32,208,209],{"class":156}," }()  ",[32,211,212],{"class":38},"\u002F\u002F blocks until someone receives\n",[32,214,216,219,221,224,227],{"class":34,"line":215},23,[32,217,218],{"class":156},"    v ",[32,220,172],{"class":148},[32,222,223],{"class":148}," \u003C-",[32,225,226],{"class":156},"ch                 ",[32,228,229],{"class":38},"\u002F\u002F receives 42, unblocks the sender\n",[32,231,233,236,239,242],{"class":34,"line":232},24,[32,234,235],{"class":156},"    fmt.",[32,237,238],{"class":152},"Println",[32,240,241],{"class":156},"(v)            ",[32,243,244],{"class":38},"\u002F\u002F 42\n",[32,246,248],{"class":34,"line":247},25,[32,249,142],{"emptyLinePlaceholder":141},[32,251,253],{"class":34,"line":252},26,[32,254,255],{"class":38},"    \u002F\u002F Buffered — asynchronous up to capacity:\n",[32,257,259,262,264,266,268,270,272,275,278],{"class":34,"line":258},27,[32,260,261],{"class":156},"    bch ",[32,263,172],{"class":148},[32,265,175],{"class":152},[32,267,178],{"class":156},[32,269,181],{"class":148},[32,271,184],{"class":148},[32,273,274],{"class":156},", ",[32,276,277],{"class":205},"3",[32,279,187],{"class":156},[32,281,283,285,287,290],{"class":34,"line":282},28,[32,284,261],{"class":156},[32,286,202],{"class":148},[32,288,289],{"class":205}," 1",[32,291,292],{"class":38},"  \u002F\u002F doesn't block (buffer has space)\n",[32,294,296,298,300],{"class":34,"line":295},29,[32,297,261],{"class":156},[32,299,202],{"class":148},[32,301,302],{"class":205}," 2\n",[32,304,306,308,310],{"class":34,"line":305},30,[32,307,261],{"class":156},[32,309,202],{"class":148},[32,311,312],{"class":205}," 3\n",[32,314,316,319],{"class":34,"line":315},31,[32,317,318],{"class":38},"    \u002F\u002F bch \u003C- 4",[32,320,321],{"class":38},"  \u002F\u002F blocks (buffer full) until someone receives\n",[32,323,325,327,329,331,333,336],{"class":34,"line":324},32,[32,326,235],{"class":156},[32,328,238],{"class":152},[32,330,178],{"class":156},[32,332,202],{"class":148},[32,334,335],{"class":156},"bch)  ",[32,337,338],{"class":38},"\u002F\u002F 1 (FIFO)\n",[32,340,342],{"class":34,"line":341},33,[32,343,344],{"class":156},"}\n",[14,346,348],{"id":347},"closing-channels-rules-and-ownership","Closing Channels — Rules and Ownership",[19,350,351,828,832],{"language":21},[23,352,354],{"className":25,"code":353,"language":21,"meta":27,"style":27},"\u002F\u002F RULE: only the SENDER closes the channel. The receiver never closes\n\u002F\u002F (it doesn't know if other senders exist).\n\u002F\u002F\n\u002F\u002F Closing signals \"no more values will be sent.\"\n\u002F\u002F Receiving from a closed channel returns the zero value with ok=false.\n\nfunc producer(out chan\u003C- int) {  \u002F\u002F send-only\n    for i := 0; i \u003C 5; i++ {\n        out \u003C- i\n    }\n    close(out)  \u002F\u002F ✅ sender closes — signals \"done\"\n}\n\nfunc consumer(in \u003C-chan int) {  \u002F\u002F receive-only\n    for v := range in {  \u002F\u002F range stops when channel is closed and drained\n        fmt.Println(v)  \u002F\u002F 0 1 2 3 4\n    }\n}\n\nfunc main() {\n    ch := make(chan int)\n    go producer(ch)\n    consumer(ch)\n}\n\n\u002F\u002F ─── Multiple senders — the coordinator pattern ───\n\u002F\u002F If multiple goroutines send, none should close directly (another might send).\n\u002F\u002F Use a coordinator goroutine that closes after all senders are done.\n\nfunc multiSender(jobs []int) \u003C-chan int {\n    out := make(chan int)\n    var wg sync.WaitGroup\n\n    for _, job := range jobs {\n        wg.Add(1)\n        go func(j int) {\n            defer wg.Done()\n            out \u003C- j  \u002F\u002F send\n        }(job)\n    }\n\n    \u002F\u002F Coordinator: close after all senders finish\n    go func() {\n        wg.Wait()\n        close(out)  \u002F\u002F ✅ safe — all sends are done\n    }()\n\n    return out\n}\n",[29,355,356,361,366,371,376,381,385,409,440,450,455,466,470,474,496,514,527,531,535,539,548,564,573,580,584,588,593,598,603,607,635,652,669,673,688,704,722,737,751,757,762,767,773,782,792,803,809,814,823],{"__ignoreMap":27},[32,357,358],{"class":34,"line":35},[32,359,360],{"class":38},"\u002F\u002F RULE: only the SENDER closes the channel. The receiver never closes\n",[32,362,363],{"class":34,"line":42},[32,364,365],{"class":38},"\u002F\u002F (it doesn't know if other senders exist).\n",[32,367,368],{"class":34,"line":48},[32,369,370],{"class":38},"\u002F\u002F\n",[32,372,373],{"class":34,"line":54},[32,374,375],{"class":38},"\u002F\u002F Closing signals \"no more values will be sent.\"\n",[32,377,378],{"class":34,"line":60},[32,379,380],{"class":38},"\u002F\u002F Receiving from a closed channel returns the zero value with ok=false.\n",[32,382,383],{"class":34,"line":66},[32,384,142],{"emptyLinePlaceholder":141},[32,386,387,389,392,394,398,401,403,406],{"class":34,"line":72},[32,388,149],{"class":148},[32,390,391],{"class":152}," producer",[32,393,178],{"class":156},[32,395,397],{"class":396},"sCrzJ","out",[32,399,400],{"class":148}," chan\u003C-",[32,402,184],{"class":148},[32,404,405],{"class":156},") {  ",[32,407,408],{"class":38},"\u002F\u002F send-only\n",[32,410,411,414,417,419,422,425,428,431,434,437],{"class":34,"line":78},[32,412,413],{"class":148},"    for",[32,415,416],{"class":156}," i ",[32,418,172],{"class":148},[32,420,421],{"class":205}," 0",[32,423,424],{"class":156},"; i ",[32,426,427],{"class":148},"\u003C",[32,429,430],{"class":205}," 5",[32,432,433],{"class":156},"; i",[32,435,436],{"class":148},"++",[32,438,439],{"class":156}," {\n",[32,441,442,445,447],{"class":34,"line":84},[32,443,444],{"class":156},"        out ",[32,446,202],{"class":148},[32,448,449],{"class":156}," i\n",[32,451,452],{"class":34,"line":90},[32,453,454],{"class":156},"    }\n",[32,456,457,460,463],{"class":34,"line":96},[32,458,459],{"class":152},"    close",[32,461,462],{"class":156},"(out)  ",[32,464,465],{"class":38},"\u002F\u002F ✅ sender closes — signals \"done\"\n",[32,467,468],{"class":34,"line":102},[32,469,344],{"class":156},[32,471,472],{"class":34,"line":108},[32,473,142],{"emptyLinePlaceholder":141},[32,475,476,478,481,483,486,489,491,493],{"class":34,"line":114},[32,477,149],{"class":148},[32,479,480],{"class":152}," consumer",[32,482,178],{"class":156},[32,484,485],{"class":396},"in",[32,487,488],{"class":148}," \u003C-chan",[32,490,184],{"class":148},[32,492,405],{"class":156},[32,494,495],{"class":38},"\u002F\u002F receive-only\n",[32,497,498,500,503,505,508,511],{"class":34,"line":120},[32,499,413],{"class":148},[32,501,502],{"class":156}," v ",[32,504,172],{"class":148},[32,506,507],{"class":148}," range",[32,509,510],{"class":156}," in {  ",[32,512,513],{"class":38},"\u002F\u002F range stops when channel is closed and drained\n",[32,515,516,519,521,524],{"class":34,"line":126},[32,517,518],{"class":156},"        fmt.",[32,520,238],{"class":152},[32,522,523],{"class":156},"(v)  ",[32,525,526],{"class":38},"\u002F\u002F 0 1 2 3 4\n",[32,528,529],{"class":34,"line":132},[32,530,454],{"class":156},[32,532,533],{"class":34,"line":138},[32,534,344],{"class":156},[32,536,537],{"class":34,"line":145},[32,538,142],{"emptyLinePlaceholder":141},[32,540,541,543,546],{"class":34,"line":160},[32,542,149],{"class":148},[32,544,545],{"class":152}," main",[32,547,157],{"class":156},[32,549,550,552,554,556,558,560,562],{"class":34,"line":166},[32,551,169],{"class":156},[32,553,172],{"class":148},[32,555,175],{"class":152},[32,557,178],{"class":156},[32,559,181],{"class":148},[32,561,184],{"class":148},[32,563,187],{"class":156},[32,565,566,568,570],{"class":34,"line":190},[32,567,193],{"class":148},[32,569,391],{"class":152},[32,571,572],{"class":156},"(ch)\n",[32,574,575,578],{"class":34,"line":215},[32,576,577],{"class":152},"    consumer",[32,579,572],{"class":156},[32,581,582],{"class":34,"line":232},[32,583,344],{"class":156},[32,585,586],{"class":34,"line":247},[32,587,142],{"emptyLinePlaceholder":141},[32,589,590],{"class":34,"line":252},[32,591,592],{"class":38},"\u002F\u002F ─── Multiple senders — the coordinator pattern ───\n",[32,594,595],{"class":34,"line":258},[32,596,597],{"class":38},"\u002F\u002F If multiple goroutines send, none should close directly (another might send).\n",[32,599,600],{"class":34,"line":282},[32,601,602],{"class":38},"\u002F\u002F Use a coordinator goroutine that closes after all senders are done.\n",[32,604,605],{"class":34,"line":295},[32,606,142],{"emptyLinePlaceholder":141},[32,608,609,611,614,616,619,622,625,628,631,633],{"class":34,"line":305},[32,610,149],{"class":148},[32,612,613],{"class":152}," multiSender",[32,615,178],{"class":156},[32,617,618],{"class":396},"jobs",[32,620,621],{"class":156}," []",[32,623,624],{"class":148},"int",[32,626,627],{"class":156},") ",[32,629,630],{"class":148},"\u003C-chan",[32,632,184],{"class":148},[32,634,439],{"class":156},[32,636,637,640,642,644,646,648,650],{"class":34,"line":315},[32,638,639],{"class":156},"    out ",[32,641,172],{"class":148},[32,643,175],{"class":152},[32,645,178],{"class":156},[32,647,181],{"class":148},[32,649,184],{"class":148},[32,651,187],{"class":156},[32,653,654,657,660,663,666],{"class":34,"line":324},[32,655,656],{"class":148},"    var",[32,658,659],{"class":156}," wg ",[32,661,662],{"class":152},"sync",[32,664,665],{"class":156},".",[32,667,668],{"class":152},"WaitGroup\n",[32,670,671],{"class":34,"line":341},[32,672,142],{"emptyLinePlaceholder":141},[32,674,676,678,681,683,685],{"class":34,"line":675},34,[32,677,413],{"class":148},[32,679,680],{"class":156}," _, job ",[32,682,172],{"class":148},[32,684,507],{"class":148},[32,686,687],{"class":156}," jobs {\n",[32,689,691,694,697,699,702],{"class":34,"line":690},35,[32,692,693],{"class":156},"        wg.",[32,695,696],{"class":152},"Add",[32,698,178],{"class":156},[32,700,701],{"class":205},"1",[32,703,187],{"class":156},[32,705,707,710,712,714,717,719],{"class":34,"line":706},36,[32,708,709],{"class":148},"        go",[32,711,196],{"class":148},[32,713,178],{"class":156},[32,715,716],{"class":396},"j",[32,718,184],{"class":148},[32,720,721],{"class":156},") {\n",[32,723,725,728,731,734],{"class":34,"line":724},37,[32,726,727],{"class":148},"            defer",[32,729,730],{"class":156}," wg.",[32,732,733],{"class":152},"Done",[32,735,736],{"class":156},"()\n",[32,738,740,743,745,748],{"class":34,"line":739},38,[32,741,742],{"class":156},"            out ",[32,744,202],{"class":148},[32,746,747],{"class":156}," j  ",[32,749,750],{"class":38},"\u002F\u002F send\n",[32,752,754],{"class":34,"line":753},39,[32,755,756],{"class":156},"        }(job)\n",[32,758,760],{"class":34,"line":759},40,[32,761,454],{"class":156},[32,763,765],{"class":34,"line":764},41,[32,766,142],{"emptyLinePlaceholder":141},[32,768,770],{"class":34,"line":769},42,[32,771,772],{"class":38},"    \u002F\u002F Coordinator: close after all senders finish\n",[32,774,776,778,780],{"class":34,"line":775},43,[32,777,193],{"class":148},[32,779,196],{"class":148},[32,781,157],{"class":156},[32,783,785,787,790],{"class":34,"line":784},44,[32,786,693],{"class":156},[32,788,789],{"class":152},"Wait",[32,791,736],{"class":156},[32,793,795,798,800],{"class":34,"line":794},45,[32,796,797],{"class":152},"        close",[32,799,462],{"class":156},[32,801,802],{"class":38},"\u002F\u002F ✅ safe — all sends are done\n",[32,804,806],{"class":34,"line":805},46,[32,807,808],{"class":156},"    }()\n",[32,810,812],{"class":34,"line":811},47,[32,813,142],{"emptyLinePlaceholder":141},[32,815,817,820],{"class":34,"line":816},48,[32,818,819],{"class":148},"    return",[32,821,822],{"class":156}," out\n",[32,824,826],{"class":34,"line":825},49,[32,827,344],{"class":156},[14,829,831],{"id":830},"directional-channels-compiler-enforced-intent","Directional Channels — Compiler-Enforced Intent",[19,833,834,1064,1072],{"language":21},[23,835,837],{"className":25,"code":836,"language":21,"meta":27,"style":27},"\u002F\u002F chan\u003C- T  — send-only (can send, can't receive)\n\u002F\u002F \u003C-chan T  — receive-only (can receive, can't send)\n\u002F\u002F chan T    — bidirectional (can send and receive)\n\n\u002F\u002F Use directional types in function signatures to document intent\n\u002F\u002F and let the compiler enforce it.\n\nfunc producer(out chan\u003C- int) {  \u002F\u002F can only send to out\n    for i := 0; i \u003C 3; i++ {\n        out \u003C- i\n    }\n    \u002F\u002F v := \u003C-out  \u002F\u002F compile error: cannot receive from send-only channel\n    close(out)\n}\n\nfunc consumer(in \u003C-chan int) {  \u002F\u002F can only receive from in\n    for v := range in {\n        fmt.Println(v)\n    }\n    \u002F\u002F in \u003C- 42  \u002F\u002F compile error: cannot send to receive-only channel\n}\n\nfunc main() {\n    ch := make(chan int)      \u002F\u002F bidirectional\n    go producer(ch)           \u002F\u002F implicitly converts to chan\u003C- int\n    consumer(ch)              \u002F\u002F implicitly converts to \u003C-chan int\n}\n",[29,838,839,844,849,854,858,863,868,872,891,914,922,926,934,941,945,949,968,981,990,994,1002,1006,1010,1018,1038,1050,1060],{"__ignoreMap":27},[32,840,841],{"class":34,"line":35},[32,842,843],{"class":38},"\u002F\u002F chan\u003C- T  — send-only (can send, can't receive)\n",[32,845,846],{"class":34,"line":42},[32,847,848],{"class":38},"\u002F\u002F \u003C-chan T  — receive-only (can receive, can't send)\n",[32,850,851],{"class":34,"line":48},[32,852,853],{"class":38},"\u002F\u002F chan T    — bidirectional (can send and receive)\n",[32,855,856],{"class":34,"line":54},[32,857,142],{"emptyLinePlaceholder":141},[32,859,860],{"class":34,"line":60},[32,861,862],{"class":38},"\u002F\u002F Use directional types in function signatures to document intent\n",[32,864,865],{"class":34,"line":66},[32,866,867],{"class":38},"\u002F\u002F and let the compiler enforce it.\n",[32,869,870],{"class":34,"line":72},[32,871,142],{"emptyLinePlaceholder":141},[32,873,874,876,878,880,882,884,886,888],{"class":34,"line":78},[32,875,149],{"class":148},[32,877,391],{"class":152},[32,879,178],{"class":156},[32,881,397],{"class":396},[32,883,400],{"class":148},[32,885,184],{"class":148},[32,887,405],{"class":156},[32,889,890],{"class":38},"\u002F\u002F can only send to out\n",[32,892,893,895,897,899,901,903,905,908,910,912],{"class":34,"line":84},[32,894,413],{"class":148},[32,896,416],{"class":156},[32,898,172],{"class":148},[32,900,421],{"class":205},[32,902,424],{"class":156},[32,904,427],{"class":148},[32,906,907],{"class":205}," 3",[32,909,433],{"class":156},[32,911,436],{"class":148},[32,913,439],{"class":156},[32,915,916,918,920],{"class":34,"line":90},[32,917,444],{"class":156},[32,919,202],{"class":148},[32,921,449],{"class":156},[32,923,924],{"class":34,"line":96},[32,925,454],{"class":156},[32,927,928,931],{"class":34,"line":102},[32,929,930],{"class":38},"    \u002F\u002F v := \u003C-out",[32,932,933],{"class":38},"  \u002F\u002F compile error: cannot receive from send-only channel\n",[32,935,936,938],{"class":34,"line":108},[32,937,459],{"class":152},[32,939,940],{"class":156},"(out)\n",[32,942,943],{"class":34,"line":114},[32,944,344],{"class":156},[32,946,947],{"class":34,"line":120},[32,948,142],{"emptyLinePlaceholder":141},[32,950,951,953,955,957,959,961,963,965],{"class":34,"line":126},[32,952,149],{"class":148},[32,954,480],{"class":152},[32,956,178],{"class":156},[32,958,485],{"class":396},[32,960,488],{"class":148},[32,962,184],{"class":148},[32,964,405],{"class":156},[32,966,967],{"class":38},"\u002F\u002F can only receive from in\n",[32,969,970,972,974,976,978],{"class":34,"line":132},[32,971,413],{"class":148},[32,973,502],{"class":156},[32,975,172],{"class":148},[32,977,507],{"class":148},[32,979,980],{"class":156}," in {\n",[32,982,983,985,987],{"class":34,"line":138},[32,984,518],{"class":156},[32,986,238],{"class":152},[32,988,989],{"class":156},"(v)\n",[32,991,992],{"class":34,"line":145},[32,993,454],{"class":156},[32,995,996,999],{"class":34,"line":160},[32,997,998],{"class":38},"    \u002F\u002F in \u003C- 42",[32,1000,1001],{"class":38},"  \u002F\u002F compile error: cannot send to receive-only channel\n",[32,1003,1004],{"class":34,"line":166},[32,1005,344],{"class":156},[32,1007,1008],{"class":34,"line":190},[32,1009,142],{"emptyLinePlaceholder":141},[32,1011,1012,1014,1016],{"class":34,"line":215},[32,1013,149],{"class":148},[32,1015,545],{"class":152},[32,1017,157],{"class":156},[32,1019,1020,1022,1024,1026,1028,1030,1032,1035],{"class":34,"line":232},[32,1021,169],{"class":156},[32,1023,172],{"class":148},[32,1025,175],{"class":152},[32,1027,178],{"class":156},[32,1029,181],{"class":148},[32,1031,184],{"class":148},[32,1033,1034],{"class":156},")      ",[32,1036,1037],{"class":38},"\u002F\u002F bidirectional\n",[32,1039,1040,1042,1044,1047],{"class":34,"line":247},[32,1041,193],{"class":148},[32,1043,391],{"class":152},[32,1045,1046],{"class":156},"(ch)           ",[32,1048,1049],{"class":38},"\u002F\u002F implicitly converts to chan\u003C- int\n",[32,1051,1052,1054,1057],{"class":34,"line":252},[32,1053,577],{"class":152},[32,1055,1056],{"class":156},"(ch)              ",[32,1058,1059],{"class":38},"\u002F\u002F implicitly converts to \u003C-chan int\n",[32,1061,1062],{"class":34,"line":258},[32,1063,344],{"class":156},[14,1065,1067,1068,1071],{"id":1066},"nil-channels-in-select-dynamic-case-control","Nil Channels in ",[29,1069,1070],{},"select"," — Dynamic Case Control",[19,1073,1074,1489,1496],{"language":21},[23,1075,1077],{"className":25,"code":1076,"language":21,"meta":27,"style":27},"\u002F\u002F A nil channel in select blocks that case FOREVER — effectively disabling it.\n\u002F\u002F This is a pattern for dynamically enabling\u002Fdisabling select cases.\n\nfunc dynamicSelect() {\n    var send chan\u003C- int = nil  \u002F\u002F disabled — this case never fires\n    var recv \u003C-chan int = nil\n\n    if shouldSend {\n        send = someChannel  \u002F\u002F enabled\n    }\n    if shouldReceive {\n        recv = someOtherChannel\n    }\n\n    select {\n    case send \u003C- 42:     \u002F\u002F only fires if send != nil\n    case v := \u003C-recv:    \u002F\u002F only fires if recv != nil\n        _ = v\n    case \u003C-time.After(time.Second):\n        fmt.Println(\"timeout\")\n    }\n}\n\n\u002F\u002F ─── Production pattern: state machine with nil channels ───\nfunc stateMachine(input \u003C-chan int, output chan\u003C- int) {\n    var pending int\n    var hasPending bool\n    var out chan\u003C- int = nil  \u002F\u002F disabled until we have something to send\n\n    for {\n        select {\n        case v, ok := \u003C-input:\n            if !ok {\n                return  \u002F\u002F input closed\n            }\n            pending = v\n            hasPending = true\n            out = output  \u002F\u002F enable the send case\n        case out \u003C- pending:  \u002F\u002F only fires when out != nil (we have pending)\n            hasPending = false\n            out = nil  \u002F\u002F disable the send case until next input\n        }\n    }\n}\n",[29,1078,1079,1084,1089,1093,1102,1123,1139,1143,1151,1165,1169,1176,1186,1190,1194,1201,1218,1234,1244,1259,1273,1277,1281,1285,1290,1317,1327,1337,1355,1359,1365,1372,1387,1398,1406,1411,1420,1430,1442,1456,1465,1476,1481,1485],{"__ignoreMap":27},[32,1080,1081],{"class":34,"line":35},[32,1082,1083],{"class":38},"\u002F\u002F A nil channel in select blocks that case FOREVER — effectively disabling it.\n",[32,1085,1086],{"class":34,"line":42},[32,1087,1088],{"class":38},"\u002F\u002F This is a pattern for dynamically enabling\u002Fdisabling select cases.\n",[32,1090,1091],{"class":34,"line":48},[32,1092,142],{"emptyLinePlaceholder":141},[32,1094,1095,1097,1100],{"class":34,"line":54},[32,1096,149],{"class":148},[32,1098,1099],{"class":152}," dynamicSelect",[32,1101,157],{"class":156},[32,1103,1104,1106,1109,1112,1114,1117,1120],{"class":34,"line":60},[32,1105,656],{"class":148},[32,1107,1108],{"class":156}," send ",[32,1110,1111],{"class":148},"chan\u003C-",[32,1113,184],{"class":148},[32,1115,1116],{"class":148}," =",[32,1118,1119],{"class":205}," nil",[32,1121,1122],{"class":38},"  \u002F\u002F disabled — this case never fires\n",[32,1124,1125,1127,1130,1132,1134,1136],{"class":34,"line":66},[32,1126,656],{"class":148},[32,1128,1129],{"class":156}," recv ",[32,1131,630],{"class":148},[32,1133,184],{"class":148},[32,1135,1116],{"class":148},[32,1137,1138],{"class":205}," nil\n",[32,1140,1141],{"class":34,"line":72},[32,1142,142],{"emptyLinePlaceholder":141},[32,1144,1145,1148],{"class":34,"line":78},[32,1146,1147],{"class":148},"    if",[32,1149,1150],{"class":156}," shouldSend {\n",[32,1152,1153,1156,1159,1162],{"class":34,"line":84},[32,1154,1155],{"class":156},"        send ",[32,1157,1158],{"class":148},"=",[32,1160,1161],{"class":156}," someChannel  ",[32,1163,1164],{"class":38},"\u002F\u002F enabled\n",[32,1166,1167],{"class":34,"line":90},[32,1168,454],{"class":156},[32,1170,1171,1173],{"class":34,"line":96},[32,1172,1147],{"class":148},[32,1174,1175],{"class":156}," shouldReceive {\n",[32,1177,1178,1181,1183],{"class":34,"line":102},[32,1179,1180],{"class":156},"        recv ",[32,1182,1158],{"class":148},[32,1184,1185],{"class":156}," someOtherChannel\n",[32,1187,1188],{"class":34,"line":108},[32,1189,454],{"class":156},[32,1191,1192],{"class":34,"line":114},[32,1193,142],{"emptyLinePlaceholder":141},[32,1195,1196,1199],{"class":34,"line":120},[32,1197,1198],{"class":148},"    select",[32,1200,439],{"class":156},[32,1202,1203,1206,1208,1210,1212,1215],{"class":34,"line":126},[32,1204,1205],{"class":148},"    case",[32,1207,1108],{"class":156},[32,1209,202],{"class":148},[32,1211,206],{"class":205},[32,1213,1214],{"class":156},":     ",[32,1216,1217],{"class":38},"\u002F\u002F only fires if send != nil\n",[32,1219,1220,1222,1224,1226,1228,1231],{"class":34,"line":132},[32,1221,1205],{"class":148},[32,1223,502],{"class":156},[32,1225,172],{"class":148},[32,1227,223],{"class":148},[32,1229,1230],{"class":156},"recv:    ",[32,1232,1233],{"class":38},"\u002F\u002F only fires if recv != nil\n",[32,1235,1236,1239,1241],{"class":34,"line":138},[32,1237,1238],{"class":156},"        _ ",[32,1240,1158],{"class":148},[32,1242,1243],{"class":156}," v\n",[32,1245,1246,1248,1250,1253,1256],{"class":34,"line":145},[32,1247,1205],{"class":148},[32,1249,223],{"class":148},[32,1251,1252],{"class":156},"time.",[32,1254,1255],{"class":152},"After",[32,1257,1258],{"class":156},"(time.Second):\n",[32,1260,1261,1263,1265,1267,1271],{"class":34,"line":160},[32,1262,518],{"class":156},[32,1264,238],{"class":152},[32,1266,178],{"class":156},[32,1268,1270],{"class":1269},"sJ6F3","\"timeout\"",[32,1272,187],{"class":156},[32,1274,1275],{"class":34,"line":166},[32,1276,454],{"class":156},[32,1278,1279],{"class":34,"line":190},[32,1280,344],{"class":156},[32,1282,1283],{"class":34,"line":215},[32,1284,142],{"emptyLinePlaceholder":141},[32,1286,1287],{"class":34,"line":232},[32,1288,1289],{"class":38},"\u002F\u002F ─── Production pattern: state machine with nil channels ───\n",[32,1291,1292,1294,1297,1299,1302,1304,1306,1308,1311,1313,1315],{"class":34,"line":247},[32,1293,149],{"class":148},[32,1295,1296],{"class":152}," stateMachine",[32,1298,178],{"class":156},[32,1300,1301],{"class":396},"input",[32,1303,488],{"class":148},[32,1305,184],{"class":148},[32,1307,274],{"class":156},[32,1309,1310],{"class":396},"output",[32,1312,400],{"class":148},[32,1314,184],{"class":148},[32,1316,721],{"class":156},[32,1318,1319,1321,1324],{"class":34,"line":252},[32,1320,656],{"class":148},[32,1322,1323],{"class":156}," pending ",[32,1325,1326],{"class":148},"int\n",[32,1328,1329,1331,1334],{"class":34,"line":258},[32,1330,656],{"class":148},[32,1332,1333],{"class":156}," hasPending ",[32,1335,1336],{"class":148},"bool\n",[32,1338,1339,1341,1344,1346,1348,1350,1352],{"class":34,"line":282},[32,1340,656],{"class":148},[32,1342,1343],{"class":156}," out ",[32,1345,1111],{"class":148},[32,1347,184],{"class":148},[32,1349,1116],{"class":148},[32,1351,1119],{"class":205},[32,1353,1354],{"class":38},"  \u002F\u002F disabled until we have something to send\n",[32,1356,1357],{"class":34,"line":295},[32,1358,142],{"emptyLinePlaceholder":141},[32,1360,1361,1363],{"class":34,"line":305},[32,1362,413],{"class":148},[32,1364,439],{"class":156},[32,1366,1367,1370],{"class":34,"line":315},[32,1368,1369],{"class":148},"        select",[32,1371,439],{"class":156},[32,1373,1374,1377,1380,1382,1384],{"class":34,"line":324},[32,1375,1376],{"class":148},"        case",[32,1378,1379],{"class":156}," v, ok ",[32,1381,172],{"class":148},[32,1383,223],{"class":148},[32,1385,1386],{"class":156},"input:\n",[32,1388,1389,1392,1395],{"class":34,"line":341},[32,1390,1391],{"class":148},"            if",[32,1393,1394],{"class":148}," !",[32,1396,1397],{"class":156},"ok {\n",[32,1399,1400,1403],{"class":34,"line":675},[32,1401,1402],{"class":148},"                return",[32,1404,1405],{"class":38},"  \u002F\u002F input closed\n",[32,1407,1408],{"class":34,"line":690},[32,1409,1410],{"class":156},"            }\n",[32,1412,1413,1416,1418],{"class":34,"line":706},[32,1414,1415],{"class":156},"            pending ",[32,1417,1158],{"class":148},[32,1419,1243],{"class":156},[32,1421,1422,1425,1427],{"class":34,"line":724},[32,1423,1424],{"class":156},"            hasPending ",[32,1426,1158],{"class":148},[32,1428,1429],{"class":205}," true\n",[32,1431,1432,1434,1436,1439],{"class":34,"line":739},[32,1433,742],{"class":156},[32,1435,1158],{"class":148},[32,1437,1438],{"class":156}," output  ",[32,1440,1441],{"class":38},"\u002F\u002F enable the send case\n",[32,1443,1444,1446,1448,1450,1453],{"class":34,"line":753},[32,1445,1376],{"class":148},[32,1447,1343],{"class":156},[32,1449,202],{"class":148},[32,1451,1452],{"class":156}," pending:  ",[32,1454,1455],{"class":38},"\u002F\u002F only fires when out != nil (we have pending)\n",[32,1457,1458,1460,1462],{"class":34,"line":759},[32,1459,1424],{"class":156},[32,1461,1158],{"class":148},[32,1463,1464],{"class":205}," false\n",[32,1466,1467,1469,1471,1473],{"class":34,"line":764},[32,1468,742],{"class":156},[32,1470,1158],{"class":148},[32,1472,1119],{"class":205},[32,1474,1475],{"class":38},"  \u002F\u002F disable the send case until next input\n",[32,1477,1478],{"class":34,"line":769},[32,1479,1480],{"class":156},"        }\n",[32,1482,1483],{"class":34,"line":775},[32,1484,454],{"class":156},[32,1486,1487],{"class":34,"line":784},[32,1488,344],{"class":156},[14,1490,1492,1493],{"id":1491},"signaldone-channels-chan-struct","Signal\u002FDone Channels — ",[29,1494,1495],{},"chan struct{}",[19,1497,1498,1779,1783],{"language":21},[23,1499,1501],{"className":25,"code":1500,"language":21,"meta":27,"style":27},"\u002F\u002F chan struct{} is the idiom for a signal channel — carries no data,\n\u002F\u002F zero bytes. close(done) signals to ALL receivers (unlike a send which\n\u002F\u002F only unblocks one receiver).\n\nfunc signalPattern() {\n    done := make(chan struct{})\n\n    \u002F\u002F Worker goroutines listen for done:\n    for i := 0; i \u003C 3; i++ {\n        go func(id int) {\n            select {\n            case \u003C-done:\n                fmt.Printf(\"worker %d: shutting down\\n\", id)\n                return\n            case \u003C-time.After(10 * time.Second):\n                fmt.Printf(\"worker %d: work done\\n\", id)\n            }\n        }(i)\n    }\n\n    \u002F\u002F Signal all workers to stop:\n    close(done)  \u002F\u002F ALL three \u003C-done unblock simultaneously\n    time.Sleep(time.Second)\n}\n\n\u002F\u002F ┌──────────────────────────────────────────────────────────────────────┐\n\u002F\u002F │ close(done) vs done \u003C- struct{}{}                                     │\n\u002F\u002F │   close: unblocks ALL receivers simultaneously (broadcast)           │\n\u002F\u002F │   send:  unblocks ONE receiver (if multiple are waiting, random)     │\n\u002F\u002F │                                                                        │\n\u002F\u002F │ For \"stop\" signals, always use close — it's a broadcast.             │\n\u002F\u002F │ For \"pass a value\", use send — it's point-to-point.                  │\n\u002F\u002F └──────────────────────────────────────────────────────────────────────┘\n",[29,1502,1503,1508,1513,1518,1522,1531,1550,1554,1559,1581,1596,1603,1613,1641,1646,1667,1688,1692,1697,1701,1705,1710,1720,1731,1735,1739,1744,1749,1754,1759,1764,1769,1774],{"__ignoreMap":27},[32,1504,1505],{"class":34,"line":35},[32,1506,1507],{"class":38},"\u002F\u002F chan struct{} is the idiom for a signal channel — carries no data,\n",[32,1509,1510],{"class":34,"line":42},[32,1511,1512],{"class":38},"\u002F\u002F zero bytes. close(done) signals to ALL receivers (unlike a send which\n",[32,1514,1515],{"class":34,"line":48},[32,1516,1517],{"class":38},"\u002F\u002F only unblocks one receiver).\n",[32,1519,1520],{"class":34,"line":54},[32,1521,142],{"emptyLinePlaceholder":141},[32,1523,1524,1526,1529],{"class":34,"line":60},[32,1525,149],{"class":148},[32,1527,1528],{"class":152}," signalPattern",[32,1530,157],{"class":156},[32,1532,1533,1536,1538,1540,1542,1544,1547],{"class":34,"line":66},[32,1534,1535],{"class":156},"    done ",[32,1537,172],{"class":148},[32,1539,175],{"class":152},[32,1541,178],{"class":156},[32,1543,181],{"class":148},[32,1545,1546],{"class":148}," struct",[32,1548,1549],{"class":156},"{})\n",[32,1551,1552],{"class":34,"line":72},[32,1553,142],{"emptyLinePlaceholder":141},[32,1555,1556],{"class":34,"line":78},[32,1557,1558],{"class":38},"    \u002F\u002F Worker goroutines listen for done:\n",[32,1560,1561,1563,1565,1567,1569,1571,1573,1575,1577,1579],{"class":34,"line":84},[32,1562,413],{"class":148},[32,1564,416],{"class":156},[32,1566,172],{"class":148},[32,1568,421],{"class":205},[32,1570,424],{"class":156},[32,1572,427],{"class":148},[32,1574,907],{"class":205},[32,1576,433],{"class":156},[32,1578,436],{"class":148},[32,1580,439],{"class":156},[32,1582,1583,1585,1587,1589,1592,1594],{"class":34,"line":90},[32,1584,709],{"class":148},[32,1586,196],{"class":148},[32,1588,178],{"class":156},[32,1590,1591],{"class":396},"id",[32,1593,184],{"class":148},[32,1595,721],{"class":156},[32,1597,1598,1601],{"class":34,"line":96},[32,1599,1600],{"class":148},"            select",[32,1602,439],{"class":156},[32,1604,1605,1608,1610],{"class":34,"line":102},[32,1606,1607],{"class":148},"            case",[32,1609,223],{"class":148},[32,1611,1612],{"class":156},"done:\n",[32,1614,1615,1618,1621,1623,1626,1629,1632,1635,1638],{"class":34,"line":108},[32,1616,1617],{"class":156},"                fmt.",[32,1619,1620],{"class":152},"Printf",[32,1622,178],{"class":156},[32,1624,1625],{"class":1269},"\"worker ",[32,1627,1628],{"class":205},"%d",[32,1630,1631],{"class":1269},": shutting down",[32,1633,1634],{"class":205},"\\n",[32,1636,1637],{"class":1269},"\"",[32,1639,1640],{"class":156},", id)\n",[32,1642,1643],{"class":34,"line":114},[32,1644,1645],{"class":148},"                return\n",[32,1647,1648,1650,1652,1654,1656,1658,1661,1664],{"class":34,"line":120},[32,1649,1607],{"class":148},[32,1651,223],{"class":148},[32,1653,1252],{"class":156},[32,1655,1255],{"class":152},[32,1657,178],{"class":156},[32,1659,1660],{"class":205},"10",[32,1662,1663],{"class":148}," *",[32,1665,1666],{"class":156}," time.Second):\n",[32,1668,1669,1671,1673,1675,1677,1679,1682,1684,1686],{"class":34,"line":126},[32,1670,1617],{"class":156},[32,1672,1620],{"class":152},[32,1674,178],{"class":156},[32,1676,1625],{"class":1269},[32,1678,1628],{"class":205},[32,1680,1681],{"class":1269},": work done",[32,1683,1634],{"class":205},[32,1685,1637],{"class":1269},[32,1687,1640],{"class":156},[32,1689,1690],{"class":34,"line":132},[32,1691,1410],{"class":156},[32,1693,1694],{"class":34,"line":138},[32,1695,1696],{"class":156},"        }(i)\n",[32,1698,1699],{"class":34,"line":145},[32,1700,454],{"class":156},[32,1702,1703],{"class":34,"line":160},[32,1704,142],{"emptyLinePlaceholder":141},[32,1706,1707],{"class":34,"line":166},[32,1708,1709],{"class":38},"    \u002F\u002F Signal all workers to stop:\n",[32,1711,1712,1714,1717],{"class":34,"line":190},[32,1713,459],{"class":152},[32,1715,1716],{"class":156},"(done)  ",[32,1718,1719],{"class":38},"\u002F\u002F ALL three \u003C-done unblock simultaneously\n",[32,1721,1722,1725,1728],{"class":34,"line":215},[32,1723,1724],{"class":156},"    time.",[32,1726,1727],{"class":152},"Sleep",[32,1729,1730],{"class":156},"(time.Second)\n",[32,1732,1733],{"class":34,"line":232},[32,1734,344],{"class":156},[32,1736,1737],{"class":34,"line":247},[32,1738,142],{"emptyLinePlaceholder":141},[32,1740,1741],{"class":34,"line":252},[32,1742,1743],{"class":38},"\u002F\u002F ┌──────────────────────────────────────────────────────────────────────┐\n",[32,1745,1746],{"class":34,"line":258},[32,1747,1748],{"class":38},"\u002F\u002F │ close(done) vs done \u003C- struct{}{}                                     │\n",[32,1750,1751],{"class":34,"line":282},[32,1752,1753],{"class":38},"\u002F\u002F │   close: unblocks ALL receivers simultaneously (broadcast)           │\n",[32,1755,1756],{"class":34,"line":295},[32,1757,1758],{"class":38},"\u002F\u002F │   send:  unblocks ONE receiver (if multiple are waiting, random)     │\n",[32,1760,1761],{"class":34,"line":305},[32,1762,1763],{"class":38},"\u002F\u002F │                                                                        │\n",[32,1765,1766],{"class":34,"line":315},[32,1767,1768],{"class":38},"\u002F\u002F │ For \"stop\" signals, always use close — it's a broadcast.             │\n",[32,1770,1771],{"class":34,"line":324},[32,1772,1773],{"class":38},"\u002F\u002F │ For \"pass a value\", use send — it's point-to-point.                  │\n",[32,1775,1776],{"class":34,"line":341},[32,1777,1778],{"class":38},"\u002F\u002F └──────────────────────────────────────────────────────────────────────┘\n",[14,1780,1782],{"id":1781},"buffer-sizing-deliberate-not-default","Buffer Sizing — Deliberate, Not Default",[19,1784,1785,2148,2152],{"language":21},[23,1786,1788],{"className":25,"code":1787,"language":21,"meta":27,"style":27},"\u002F\u002F Buffer size is a CONCURRENCY DECISION, not a performance optimization.\n\u002F\u002F\n\u002F\u002F Unbuffered (size 0): synchronous — sender and receiver rendezvous.\n\u002F\u002F   Use when the sender must know the receiver got the value (handoff).\n\u002F\u002F\n\u002F\u002F Buffered (size N): asynchronous up to N — decouples sender\u002Freceiver.\n\u002F\u002F   Use when rates differ (producer bursts, consumer processes steadily).\n\u002F\u002F   Size = the burst size or the number of workers.\n\n\u002F\u002F ❌ ANTI-PATTERN: using a buffer to \"fix\" a deadlock\n\u002F\u002F   ch := make(chan int, 100)  \u002F\u002F \"it was deadlocking, so I buffered\"\n\u002F\u002F   The buffer DELAYS the deadlock, doesn't prevent it. Fix the design.\n\n\u002F\u002F ✅ CORRECT: buffer sized to match workers\nfunc workerPool(jobs []Job, numWorkers int) {\n    jobsCh := make(chan Job, numWorkers)     \u002F\u002F buffer = worker count\n    resultsCh := make(chan Result, numWorkers)\n\n    \u002F\u002F Start workers\n    var wg sync.WaitGroup\n    for i := 0; i \u003C numWorkers; i++ {\n        wg.Add(1)\n        go func() {\n            defer wg.Done()\n            for j := range jobsCh {\n                resultsCh \u003C- process(j)\n            }\n        }()\n    }\n\n    \u002F\u002F Feed jobs (buffer prevents blocking if workers are slow)\n    for _, j := range jobs {\n        jobsCh \u003C- j\n    }\n    close(jobsCh)\n\n    \u002F\u002F Collect results\n    go func() {\n        wg.Wait()\n        close(resultsCh)\n    }()\n    for r := range resultsCh {\n        _ = r\n    }\n}\n",[29,1789,1790,1795,1799,1804,1809,1813,1818,1823,1828,1832,1837,1845,1850,1854,1859,1884,1906,1925,1929,1934,1946,1967,1979,1987,1997,2012,2025,2029,2034,2038,2042,2047,2060,2070,2074,2081,2085,2090,2098,2106,2113,2117,2131,2140,2144],{"__ignoreMap":27},[32,1791,1792],{"class":34,"line":35},[32,1793,1794],{"class":38},"\u002F\u002F Buffer size is a CONCURRENCY DECISION, not a performance optimization.\n",[32,1796,1797],{"class":34,"line":42},[32,1798,370],{"class":38},[32,1800,1801],{"class":34,"line":48},[32,1802,1803],{"class":38},"\u002F\u002F Unbuffered (size 0): synchronous — sender and receiver rendezvous.\n",[32,1805,1806],{"class":34,"line":54},[32,1807,1808],{"class":38},"\u002F\u002F   Use when the sender must know the receiver got the value (handoff).\n",[32,1810,1811],{"class":34,"line":60},[32,1812,370],{"class":38},[32,1814,1815],{"class":34,"line":66},[32,1816,1817],{"class":38},"\u002F\u002F Buffered (size N): asynchronous up to N — decouples sender\u002Freceiver.\n",[32,1819,1820],{"class":34,"line":72},[32,1821,1822],{"class":38},"\u002F\u002F   Use when rates differ (producer bursts, consumer processes steadily).\n",[32,1824,1825],{"class":34,"line":78},[32,1826,1827],{"class":38},"\u002F\u002F   Size = the burst size or the number of workers.\n",[32,1829,1830],{"class":34,"line":84},[32,1831,142],{"emptyLinePlaceholder":141},[32,1833,1834],{"class":34,"line":90},[32,1835,1836],{"class":38},"\u002F\u002F ❌ ANTI-PATTERN: using a buffer to \"fix\" a deadlock\n",[32,1838,1839,1842],{"class":34,"line":96},[32,1840,1841],{"class":38},"\u002F\u002F   ch := make(chan int, 100)",[32,1843,1844],{"class":38},"  \u002F\u002F \"it was deadlocking, so I buffered\"\n",[32,1846,1847],{"class":34,"line":102},[32,1848,1849],{"class":38},"\u002F\u002F   The buffer DELAYS the deadlock, doesn't prevent it. Fix the design.\n",[32,1851,1852],{"class":34,"line":108},[32,1853,142],{"emptyLinePlaceholder":141},[32,1855,1856],{"class":34,"line":114},[32,1857,1858],{"class":38},"\u002F\u002F ✅ CORRECT: buffer sized to match workers\n",[32,1860,1861,1863,1866,1868,1870,1872,1875,1877,1880,1882],{"class":34,"line":120},[32,1862,149],{"class":148},[32,1864,1865],{"class":152}," workerPool",[32,1867,178],{"class":156},[32,1869,618],{"class":396},[32,1871,621],{"class":156},[32,1873,1874],{"class":152},"Job",[32,1876,274],{"class":156},[32,1878,1879],{"class":396},"numWorkers",[32,1881,184],{"class":148},[32,1883,721],{"class":156},[32,1885,1886,1889,1891,1893,1895,1897,1900,1903],{"class":34,"line":126},[32,1887,1888],{"class":156},"    jobsCh ",[32,1890,172],{"class":148},[32,1892,175],{"class":152},[32,1894,178],{"class":156},[32,1896,181],{"class":148},[32,1898,1899],{"class":152}," Job",[32,1901,1902],{"class":156},", numWorkers)     ",[32,1904,1905],{"class":38},"\u002F\u002F buffer = worker count\n",[32,1907,1908,1911,1913,1915,1917,1919,1922],{"class":34,"line":132},[32,1909,1910],{"class":156},"    resultsCh ",[32,1912,172],{"class":148},[32,1914,175],{"class":152},[32,1916,178],{"class":156},[32,1918,181],{"class":148},[32,1920,1921],{"class":152}," Result",[32,1923,1924],{"class":156},", numWorkers)\n",[32,1926,1927],{"class":34,"line":138},[32,1928,142],{"emptyLinePlaceholder":141},[32,1930,1931],{"class":34,"line":145},[32,1932,1933],{"class":38},"    \u002F\u002F Start workers\n",[32,1935,1936,1938,1940,1942,1944],{"class":34,"line":160},[32,1937,656],{"class":148},[32,1939,659],{"class":156},[32,1941,662],{"class":152},[32,1943,665],{"class":156},[32,1945,668],{"class":152},[32,1947,1948,1950,1952,1954,1956,1958,1960,1963,1965],{"class":34,"line":166},[32,1949,413],{"class":148},[32,1951,416],{"class":156},[32,1953,172],{"class":148},[32,1955,421],{"class":205},[32,1957,424],{"class":156},[32,1959,427],{"class":148},[32,1961,1962],{"class":156}," numWorkers; i",[32,1964,436],{"class":148},[32,1966,439],{"class":156},[32,1968,1969,1971,1973,1975,1977],{"class":34,"line":190},[32,1970,693],{"class":156},[32,1972,696],{"class":152},[32,1974,178],{"class":156},[32,1976,701],{"class":205},[32,1978,187],{"class":156},[32,1980,1981,1983,1985],{"class":34,"line":215},[32,1982,709],{"class":148},[32,1984,196],{"class":148},[32,1986,157],{"class":156},[32,1988,1989,1991,1993,1995],{"class":34,"line":232},[32,1990,727],{"class":148},[32,1992,730],{"class":156},[32,1994,733],{"class":152},[32,1996,736],{"class":156},[32,1998,1999,2002,2005,2007,2009],{"class":34,"line":247},[32,2000,2001],{"class":148},"            for",[32,2003,2004],{"class":156}," j ",[32,2006,172],{"class":148},[32,2008,507],{"class":148},[32,2010,2011],{"class":156}," jobsCh {\n",[32,2013,2014,2017,2019,2022],{"class":34,"line":252},[32,2015,2016],{"class":156},"                resultsCh ",[32,2018,202],{"class":148},[32,2020,2021],{"class":152}," process",[32,2023,2024],{"class":156},"(j)\n",[32,2026,2027],{"class":34,"line":258},[32,2028,1410],{"class":156},[32,2030,2031],{"class":34,"line":282},[32,2032,2033],{"class":156},"        }()\n",[32,2035,2036],{"class":34,"line":295},[32,2037,454],{"class":156},[32,2039,2040],{"class":34,"line":305},[32,2041,142],{"emptyLinePlaceholder":141},[32,2043,2044],{"class":34,"line":315},[32,2045,2046],{"class":38},"    \u002F\u002F Feed jobs (buffer prevents blocking if workers are slow)\n",[32,2048,2049,2051,2054,2056,2058],{"class":34,"line":324},[32,2050,413],{"class":148},[32,2052,2053],{"class":156}," _, j ",[32,2055,172],{"class":148},[32,2057,507],{"class":148},[32,2059,687],{"class":156},[32,2061,2062,2065,2067],{"class":34,"line":341},[32,2063,2064],{"class":156},"        jobsCh ",[32,2066,202],{"class":148},[32,2068,2069],{"class":156}," j\n",[32,2071,2072],{"class":34,"line":675},[32,2073,454],{"class":156},[32,2075,2076,2078],{"class":34,"line":690},[32,2077,459],{"class":152},[32,2079,2080],{"class":156},"(jobsCh)\n",[32,2082,2083],{"class":34,"line":706},[32,2084,142],{"emptyLinePlaceholder":141},[32,2086,2087],{"class":34,"line":724},[32,2088,2089],{"class":38},"    \u002F\u002F Collect results\n",[32,2091,2092,2094,2096],{"class":34,"line":739},[32,2093,193],{"class":148},[32,2095,196],{"class":148},[32,2097,157],{"class":156},[32,2099,2100,2102,2104],{"class":34,"line":753},[32,2101,693],{"class":156},[32,2103,789],{"class":152},[32,2105,736],{"class":156},[32,2107,2108,2110],{"class":34,"line":759},[32,2109,797],{"class":152},[32,2111,2112],{"class":156},"(resultsCh)\n",[32,2114,2115],{"class":34,"line":764},[32,2116,808],{"class":156},[32,2118,2119,2121,2124,2126,2128],{"class":34,"line":769},[32,2120,413],{"class":148},[32,2122,2123],{"class":156}," r ",[32,2125,172],{"class":148},[32,2127,507],{"class":148},[32,2129,2130],{"class":156}," resultsCh {\n",[32,2132,2133,2135,2137],{"class":34,"line":775},[32,2134,1238],{"class":156},[32,2136,1158],{"class":148},[32,2138,2139],{"class":156}," r\n",[32,2141,2142],{"class":34,"line":784},[32,2143,454],{"class":156},[32,2145,2146],{"class":34,"line":794},[32,2147,344],{"class":156},[14,2149,2151],{"id":2150},"channel-memory-mechanics","Channel Memory Mechanics",[19,2153,2154,2289,2293,2356,2360,2460,2464],{"language":21},[23,2155,2157],{"className":25,"code":2156,"language":21,"meta":27,"style":27},"\u002F\u002F A channel is a pointer to a runtime hchan struct:\n\u002F\u002F   type hchan struct {\n\u002F\u002F       qcount   uint           \u002F\u002F number of buffered elements\n\u002F\u002F       dataqsiz uint           \u002F\u002F buffer capacity\n\u002F\u002F       buf      unsafe.Pointer \u002F\u002F circular buffer (for buffered channels)\n\u002F\u002F       elemsize uint16         \u002F\u002F element size in bytes\n\u002F\u002F       sendx    uint           \u002F\u002F send index in circular buffer\n\u002F\u002F       recvx    uint           \u002F\u002F receive index in circular buffer\n\u002F\u002F       recvq    waitq          \u002F\u002F list of goroutines waiting to receive\n\u002F\u002F       sendq    waitq          \u002F\u002F list of goroutines waiting to send\n\u002F\u002F       lock     mutex          \u002F\u002F protects the hchan struct\n\u002F\u002F   }\n\u002F\u002F\n\u002F\u002F Memory per channel:\n\u002F\u002F   - hchan struct: ~96 bytes\n\u002F\u002F   - Buffer (buffered): capacity × elementSize bytes\n\u002F\u002F   - Each blocked goroutine: ~2KB stack (on the sendq\u002Frecvq)\n\u002F\u002F\n\u002F\u002F A channel with 1000 ints: 96 + 1000×8 = ~8KB\n\u002F\u002F A channel with 1M structs (100 bytes each): 96 + 1M×100 = ~100MB\n\u002F\u002F   — be careful with large buffers for big element types\n",[29,2158,2159,2164,2169,2177,2185,2193,2201,2209,2217,2225,2233,2241,2246,2250,2255,2260,2265,2270,2274,2279,2284],{"__ignoreMap":27},[32,2160,2161],{"class":34,"line":35},[32,2162,2163],{"class":38},"\u002F\u002F A channel is a pointer to a runtime hchan struct:\n",[32,2165,2166],{"class":34,"line":42},[32,2167,2168],{"class":38},"\u002F\u002F   type hchan struct {\n",[32,2170,2171,2174],{"class":34,"line":48},[32,2172,2173],{"class":38},"\u002F\u002F       qcount   uint",[32,2175,2176],{"class":38},"           \u002F\u002F number of buffered elements\n",[32,2178,2179,2182],{"class":34,"line":54},[32,2180,2181],{"class":38},"\u002F\u002F       dataqsiz uint",[32,2183,2184],{"class":38},"           \u002F\u002F buffer capacity\n",[32,2186,2187,2190],{"class":34,"line":60},[32,2188,2189],{"class":38},"\u002F\u002F       buf      unsafe.Pointer",[32,2191,2192],{"class":38}," \u002F\u002F circular buffer (for buffered channels)\n",[32,2194,2195,2198],{"class":34,"line":66},[32,2196,2197],{"class":38},"\u002F\u002F       elemsize uint16",[32,2199,2200],{"class":38},"         \u002F\u002F element size in bytes\n",[32,2202,2203,2206],{"class":34,"line":72},[32,2204,2205],{"class":38},"\u002F\u002F       sendx    uint",[32,2207,2208],{"class":38},"           \u002F\u002F send index in circular buffer\n",[32,2210,2211,2214],{"class":34,"line":78},[32,2212,2213],{"class":38},"\u002F\u002F       recvx    uint",[32,2215,2216],{"class":38},"           \u002F\u002F receive index in circular buffer\n",[32,2218,2219,2222],{"class":34,"line":84},[32,2220,2221],{"class":38},"\u002F\u002F       recvq    waitq",[32,2223,2224],{"class":38},"          \u002F\u002F list of goroutines waiting to receive\n",[32,2226,2227,2230],{"class":34,"line":90},[32,2228,2229],{"class":38},"\u002F\u002F       sendq    waitq",[32,2231,2232],{"class":38},"          \u002F\u002F list of goroutines waiting to send\n",[32,2234,2235,2238],{"class":34,"line":96},[32,2236,2237],{"class":38},"\u002F\u002F       lock     mutex",[32,2239,2240],{"class":38},"          \u002F\u002F protects the hchan struct\n",[32,2242,2243],{"class":34,"line":102},[32,2244,2245],{"class":38},"\u002F\u002F   }\n",[32,2247,2248],{"class":34,"line":108},[32,2249,370],{"class":38},[32,2251,2252],{"class":34,"line":114},[32,2253,2254],{"class":38},"\u002F\u002F Memory per channel:\n",[32,2256,2257],{"class":34,"line":120},[32,2258,2259],{"class":38},"\u002F\u002F   - hchan struct: ~96 bytes\n",[32,2261,2262],{"class":34,"line":126},[32,2263,2264],{"class":38},"\u002F\u002F   - Buffer (buffered): capacity × elementSize bytes\n",[32,2266,2267],{"class":34,"line":132},[32,2268,2269],{"class":38},"\u002F\u002F   - Each blocked goroutine: ~2KB stack (on the sendq\u002Frecvq)\n",[32,2271,2272],{"class":34,"line":138},[32,2273,370],{"class":38},[32,2275,2276],{"class":34,"line":145},[32,2277,2278],{"class":38},"\u002F\u002F A channel with 1000 ints: 96 + 1000×8 = ~8KB\n",[32,2280,2281],{"class":34,"line":160},[32,2282,2283],{"class":38},"\u002F\u002F A channel with 1M structs (100 bytes each): 96 + 1M×100 = ~100MB\n",[32,2285,2286],{"class":34,"line":166},[32,2287,2288],{"class":38},"\u002F\u002F   — be careful with large buffers for big element types\n",[14,2290,2292],{"id":2291},"tips-tricks","💡 Tips & Tricks",[2294,2295,2296,2311,2316,2325,2337,2342],"ul",{},[2297,2298,2299,2303,2304,2306,2307,2310],"li",{},[2300,2301,2302],"strong",{},"Idiom",": use ",[29,2305,1495],{}," for signal\u002Fdone channels — zero bytes, signals \"event only, no data.\" ",[29,2308,2309],{},"close(done)"," broadcasts to all receivers simultaneously.",[2297,2312,2313,2315],{},[2300,2314,2302],{},": the sender closes the channel — the receiver never closes (it doesn't know if other senders exist). For multiple senders, use a coordinator (WaitGroup + close after all done).",[2297,2317,2318,2320,2321,2324],{},[2300,2319,2302],{},": use directional channel types in function signatures (",[29,2322,2323],{},"func f(in \u003C-chan int, out chan\u003C- int)",") — documents intent, compiler enforces. Convert bidirectional to directional implicitly on call.",[2297,2326,2327,2329,2330,2332,2333,2336],{},[2300,2328,2302],{},": use a nil channel in ",[29,2331,1070],{}," to disable a case dynamically — assigning ",[29,2334,2335],{},"nil"," makes that case block forever (never fires). Pattern for state machines and conditional send\u002Freceive.",[2297,2338,2339,2341],{},[2300,2340,2302],{},": use buffered channels to decouple producer\u002Fconsumer when rates differ — a buffer absorbs bursts. Don't use buffering to \"fix\" a deadlock; size the buffer deliberately (worker count or expected burst).",[2297,2343,2344,2347,2348,2351,2352,2355],{},[2300,2345,2346],{},"Debug",": ",[29,2349,2350],{},"len(ch)"," and ",[29,2353,2354],{},"cap(ch)"," are rarely useful for synchronization — the values change immediately as goroutines send\u002Freceive. Don't use them for sync logic. Use them only for monitoring\u002Fmetrics.",[14,2357,2359],{"id":2358},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[2294,2361,2362,2368,2378,2387,2399,2408,2414,2430,2440,2451],{},[2297,2363,2364,2367],{},[2300,2365,2366],{},"Sending to a closed channel panics",": only the sender closes, and only after all sends. Receiving from a closed channel is fine (zero value, ok=false).",[2297,2369,2370,2373,2374,2377],{},[2300,2371,2372],{},"Closing a closed channel panics",": double-close is a runtime panic. Use ",[29,2375,2376],{},"sync.Once"," if closing might be called multiple times.",[2297,2379,2380,2347,2383,2386],{},[2300,2381,2382],{},"Closing a nil channel panics",[29,2384,2385],{},"var ch chan int; close(ch)"," → panic.",[2297,2388,2389,2347,2392,2395,2396,2398],{},[2300,2390,2391],{},"Receiving from a nil channel blocks forever",[29,2393,2394],{},"var ch chan int; \u003C-ch"," hangs. Useful in ",[29,2397,1070],{}," (disables the case), a bug if unintended.",[2297,2400,2401,2347,2404,2407],{},[2300,2402,2403],{},"Unbuffered channels are synchronous",[29,2405,2406],{},"ch \u003C- v"," blocks until a receiver is ready. A sender with no receiver deadlocks. Ensure a receiver is running or use a buffer.",[2297,2409,2410,2413],{},[2300,2411,2412],{},"Buffered channels hide deadlocks temporarily",": a buffer full of sends with no receiver eventually deadlocks. The buffer delays, not prevents.",[2297,2415,2416,2347,2422,2425,2426,2429],{},[2300,2417,2418,2421],{},[29,2419,2420],{},"range"," over a channel blocks until close",[29,2423,2424],{},"for v := range ch"," never returns unless ",[29,2427,2428],{},"ch"," is closed. Forgetting to close leaves the range goroutine stuck.",[2297,2431,2432,2435,2436,2439],{},[2300,2433,2434],{},"Multiple senders, one closer",": if multiple goroutines send, none should close directly. Use a coordinator or ",[29,2437,2438],{},"context"," to signal shutdown.",[2297,2441,2442,2450],{},[2300,2443,2444,2446,2447,2449],{},[29,2445,2350],{},"\u002F",[29,2448,2354],{}," changes immediately",": the values are stale by the time you use them. Don't use for synchronization.",[2297,2452,2453,2347,2456,2459],{},[2300,2454,2455],{},"Channel capacity is fixed",[29,2457,2458],{},"make(chan T, n)"," — can't resize. Pick the right capacity at creation.",[14,2461,2463],{"id":2462},"quick-quiz","🧠 Quick Quiz",[19,2465,2466,2588],{"language":21},[23,2467,2469],{"className":25,"code":2468,"language":21,"meta":27,"style":27},"func main() {\n    ch := make(chan int, 2)\n    ch \u003C- 1\n    ch \u003C- 2\n    close(ch)\n    v1, ok1 := \u003C-ch\n    v2, ok2 := \u003C-ch\n    v3, ok3 := \u003C-ch\n    fmt.Println(v1, ok1)\n    fmt.Println(v2, ok2)\n    fmt.Println(v3, ok3)\n}\n",[29,2470,2471,2479,2500,2509,2517,2523,2535,2546,2557,2566,2575,2584],{"__ignoreMap":27},[32,2472,2473,2475,2477],{"class":34,"line":35},[32,2474,149],{"class":148},[32,2476,545],{"class":152},[32,2478,157],{"class":156},[32,2480,2481,2483,2485,2487,2489,2491,2493,2495,2498],{"class":34,"line":42},[32,2482,169],{"class":156},[32,2484,172],{"class":148},[32,2486,175],{"class":152},[32,2488,178],{"class":156},[32,2490,181],{"class":148},[32,2492,184],{"class":148},[32,2494,274],{"class":156},[32,2496,2497],{"class":205},"2",[32,2499,187],{"class":156},[32,2501,2502,2504,2506],{"class":34,"line":48},[32,2503,169],{"class":156},[32,2505,202],{"class":148},[32,2507,2508],{"class":205}," 1\n",[32,2510,2511,2513,2515],{"class":34,"line":54},[32,2512,169],{"class":156},[32,2514,202],{"class":148},[32,2516,302],{"class":205},[32,2518,2519,2521],{"class":34,"line":60},[32,2520,459],{"class":152},[32,2522,572],{"class":156},[32,2524,2525,2528,2530,2532],{"class":34,"line":66},[32,2526,2527],{"class":156},"    v1, ok1 ",[32,2529,172],{"class":148},[32,2531,223],{"class":148},[32,2533,2534],{"class":156},"ch\n",[32,2536,2537,2540,2542,2544],{"class":34,"line":72},[32,2538,2539],{"class":156},"    v2, ok2 ",[32,2541,172],{"class":148},[32,2543,223],{"class":148},[32,2545,2534],{"class":156},[32,2547,2548,2551,2553,2555],{"class":34,"line":78},[32,2549,2550],{"class":156},"    v3, ok3 ",[32,2552,172],{"class":148},[32,2554,223],{"class":148},[32,2556,2534],{"class":156},[32,2558,2559,2561,2563],{"class":34,"line":84},[32,2560,235],{"class":156},[32,2562,238],{"class":152},[32,2564,2565],{"class":156},"(v1, ok1)\n",[32,2567,2568,2570,2572],{"class":34,"line":90},[32,2569,235],{"class":156},[32,2571,238],{"class":152},[32,2573,2574],{"class":156},"(v2, ok2)\n",[32,2576,2577,2579,2581],{"class":34,"line":96},[32,2578,235],{"class":156},[32,2580,238],{"class":152},[32,2582,2583],{"class":156},"(v3, ok3)\n",[32,2585,2586],{"class":34,"line":102},[32,2587,344],{"class":156},[2589,2590,2591],"p",{},"What's printed?",[2593,2594,2595,2599,2607,2614,2636],"details",{},[2596,2597,2598],"summary",{},"Answer",[23,2600,2605],{"className":2601,"code":2603,"language":2604},[2602],"language-text","1 true\n2 true\n0 false\n","text",[29,2606,2603],{"__ignoreMap":27},[2589,2608,2609,2610,2613],{},"The channel has 2 buffered values. After ",[29,2611,2612],{},"close(ch)",":",[2294,2615,2616,2623,2629],{},[2297,2617,2618,2619,2622],{},"First receive: ",[29,2620,2621],{},"v1=1, ok1=true"," (buffered value)",[2297,2624,2625,2626,2622],{},"Second receive: ",[29,2627,2628],{},"v2=2, ok2=true",[2297,2630,2631,2632,2635],{},"Third receive: ",[29,2633,2634],{},"v3=0, ok3=false"," (buffer drained, channel closed → zero value, ok=false)",[2589,2637,2638,2641,2642,2644,2645,2648],{},[29,2639,2640],{},"ok=false"," is how you detect \"channel closed and drained.\" This is why ",[29,2643,2420],{}," over a channel works — it receives until ",[29,2646,2647],{},"ok"," is false, then stops.",[14,2650,2652],{"id":2651},"whats-next","📚 What's Next",[2589,2654,2655,2656,2661,2662,2665],{},"→ ",[2657,2658,2660],"a",{"href":2659},"\u002Fgo\u002F18-select-and-multiplexing","18 — Select & Multiplexing"," — timeout patterns, fan-in, priority selects, and the ",[29,2663,2664],{},"time.After"," leak.",[2667,2668,2669],"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 .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}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}",{"title":27,"searchDepth":42,"depth":42,"links":2671},[2672,2673,2674],{"id":16,"depth":42,"text":17},{"id":347,"depth":42,"text":348},{"id":2651,"depth":42,"text":2652},"Unbuffered vs buffered semantics, close rules and ownership, directional channels, nil channel patterns, and channel memory mechanics.","md",{},"\u002Fgo\u002F17-channels",{"title":5,"description":2675},"go\u002F17-channels","z1Pja1CDlwET9IuaM_GQFqNtOqBUQUDcgWqlTwGQnrU",1789924648580]