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