io.ReadFull în Go

ReadFull umple complet buffer-ul din Reader; ReadAtLeast citește cel puțin min octeți.

Sintaxă
func ReadFull(r Reader, buf []byte) (n int, err error)
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)

Ce face io.ReadFull

Un singur Read poate returna mai puțini octeți decât ai cerut. io.ReadFull repetă citirea până umple tot buf. Dacă sursa se termină înainte, returnează io.ErrUnexpectedEOF (unii octeți citiți) sau io.EOF (niciun octet).

io.ReadAtLeast este forma generală: citește până are cel puțin min octeți (poate citi mai mulți, până la len(buf)). ReadFull(r, buf) este echivalent cu ReadAtLeast(r, buf, len(buf)). Dacă min > len(buf), primești io.ErrShortBuffer.

Folosești aceste funcții la formate binare cu dimensiune fixă: antete de fișiere, mesaje de rețea cu lungime cunoscută.

Parametri

Parametru Descriere
r Sursa.
buf Buffer-ul de umplut.
min La ReadAtLeast: numărul minim de octeți ceruți.

Ce returnează

Numărul de octeți citiți și nil la succes, altfel io.EOF, io.ErrUnexpectedEOF sau altă eroare.

Exemple

Exemplul 1: Un antet de lungime fixă

package main

import (
    "fmt"
    "io"
    "strings"
)

func main() {
    r := strings.NewReader("V02|2025-03-14|restul datelor")
    antet := make([]byte, 15)
    n, err := io.ReadFull(r, antet)
    fmt.Printf("%d octeți: %q, eroare: %v\n", n, antet, err)
}

Rezultat

15 octeți: "V02|2025-03-14|", eroare: <nil>

Exemplul 2: Cele trei cazuri de sfârșit

package main

import (
    "fmt"
    "io"
    "strings"
)

func main() {
    for _, sursa := range []string{"abcdef", "abc", ""} {
        buf := make([]byte, 5)
        n, err := io.ReadFull(strings.NewReader(sursa), buf)
        fmt.Printf("sursa %-8q -> n=%d, eroare=%v\n", sursa, n, err)
    }
}

Rezultat

sursa "abcdef" -> n=5, eroare=<nil>
sursa "abc"    -> n=3, eroare=unexpected EOF
sursa ""       -> n=0, eroare=EOF

Exemplul 3: ReadAtLeast

package main

import (
    "fmt"
    "io"
    "strings"
)

func main() {
    buf := make([]byte, 10)
    n, err := io.ReadAtLeast(strings.NewReader("Brașov, Sibiu"), buf, 4)
    fmt.Printf("n=%d %q %v\n", n, buf[:n], err)

    n, err = io.ReadAtLeast(strings.NewReader("ab"), buf, 4)
    fmt.Printf("n=%d %v\n", n, err)

    _, err = io.ReadAtLeast(strings.NewReader("abc"), make([]byte, 2), 4)
    fmt.Println(err)
}

Rezultat

n=10 "Brașov, S" <nil>
n=2 unexpected EOF
short buffer

Greșeli frecvente

  • Folosești un singur r.Read(buf) și presupui că buffer-ul este plin. Pe rețea mai ales, datele vin pe bucăți.
  • Compari doar cu io.EOF. Când sursa se termină la mijlocul buffer-ului, eroarea este io.ErrUnexpectedEOF.

Comenzi înrudite

  • io.ReadAll: Citește tot ce oferă un Reader, până la final, și returnează datele ca slice de octeți.
  • io.CopyN: Copiază exact n octeți dintr-un Reader într-un Writer (sau mai puțini, cu eroare, dacă sursa se termină).
  • os.File.Read: Citește din fișier cel mult len(b) octeți în slice-ul b și returnează câți a citit.
  • io.Reader: Interfața pentru orice sursă de date din care se poate citi: fișiere, text, conexiuni, răspunsuri HTTP.