bufio.NewWriter în Go

Învelește un io.Writer într-un bufio.Writer, care strânge scrierile mici într-un buffer și le trimite în blocuri.

Sintaxă
func NewWriter(w io.Writer) *Writer
func NewWriterSize(w io.Writer, size int) *Writer

Ce face bufio.NewWriter

Fiecare scriere directă într-un fișier sau pe ecran este un apel către sistemul de operare, relativ lent. bufio.NewWriter creează un *bufio.Writer cu un buffer de 4096 octeți: scrierile se adună în memorie și ajung la destinație doar când buffer-ul se umple sau când apelezi Flush.

Diferența de viteză se vede la mii de scrieri mici (rânduri de CSV, rezultate afișate într-o buclă). Regula de aur: la final apelezi Flush(), altfel ultimele date rămân în buffer și se pierd.

Parametri

Parametru Descriere
w Destinația (fișier, os.Stdout, conexiune).
size La NewWriterSize: dimensiunea buffer-ului.

Ce returnează

Un *bufio.Writer nou.

Exemple

Exemplul 1: Scrierea rapidă a unui fișier mare

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    f, err := os.Create("numere.txt")
    if err != nil {
        fmt.Println("eroare:", err)
        return
    }
    defer f.Close()

    w := bufio.NewWriter(f)
    for i := 1; i <= 10000; i++ {
        fmt.Fprintln(w, i)
    }
    if err := w.Flush(); err != nil {
        fmt.Println("eroare:", err)
        return
    }
    info, _ := f.Stat()
    fmt.Println("dimensiune:", info.Size(), "octeți")
}

Rezultat

dimensiune: 48894 octeți

Exemplul 2: Buffer-ul se golește singur când se umple

Destinația noastră afișează fiecare scriere reală. Cu un buffer de 16 octeți, cele cinci WriteString produc doar două scrieri: una când buffer-ul se umple, una la Flush.

package main

import (
    "bufio"
    "fmt"
)

type ecran struct{}

func (ecran) Write(p []byte) (int, error) {
    fmt.Printf("-> scriere reală: %q\n", p)
    return len(p), nil
}

func main() {
    w := bufio.NewWriterSize(ecran{}, 16)
    for _, cuvant := range []string{"unu ", "doi ", "trei ", "patru ", "cinci"} {
        w.WriteString(cuvant)
    }
    fmt.Println("în buffer înainte de Flush:", w.Buffered(), "octeți")
    w.Flush()
}

Rezultat

-> scriere reală: "unu doi trei pat"
în buffer înainte de Flush: 8 octeți
-> scriere reală: "ru cinci"

Greșeli frecvente

  • Uiți Flush. Fișierul rămâne gol sau fără ultimele rânduri, fără nicio eroare.
  • Pui defer w.Flush() și defer f.Close() în ordinea greșită. Defer-urile rulează invers: scrie întâi defer f.Close(), apoi defer w.Flush(), sau apelează Flush explicit și verifică eroarea.
  • Apelezi os.Exit înainte de Flush. Defer-urile nu mai rulează și datele se pierd.

Comenzi înrudite

  • bufio.Writer.Flush: Trimite la destinație toate datele rămase în buffer-ul unui bufio.Writer.
  • bufio.Writer.WriteString: WriteString adaugă un text în buffer; WriteRune adaugă un singur caracter Unicode, codat UTF-8.
  • os.File.Write: Scrie octeți (Write) sau text (WriteString) în fișier, la poziția curentă.
  • io.Writer: Interfața pentru orice destinație în care se pot scrie octeți: fișiere, ecran, buffer-e, răspunsuri HTTP.