io.LimitReader în Go

Învelește un Reader astfel încât să poată fi citiți din el cel mult n octeți; după aceea dă io.EOF.

Sintaxă
func LimitReader(r Reader, n int64) Reader

Ce face io.LimitReader

io.LimitReader returnează un Reader care citește din r, dar se oprește după n octeți și raportează io.EOF, chiar dacă sursa mai are date. Restul datelor rămân necitite în r.

Este protecția simplă împotriva datelor prea mari: io.ReadAll(io.LimitReader(r, 1<<20)) citește cel mult 1 MB. Atenție: ce depășește limita este tăiat în tăcere; ca să afli că sursa era prea mare, citește n+1 octeți și verifică lungimea. Pentru cereri HTTP există http.MaxBytesReader, care dă eroare.

Parametri

Parametru Descriere
r Sursa.
n Numărul maxim de octeți.

Ce returnează

Un io.Reader (concret, *io.LimitedReader).

Exemple

Exemplul 1: Primii octeți dintr-o sursă

package main

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

func main() {
    sursa := strings.NewReader("Universitatea Alexandru Ioan Cuza din Iași")
    primii, _ := io.ReadAll(io.LimitReader(sursa, 13))
    fmt.Printf("%q\n", primii)

    rest, _ := io.ReadAll(sursa)
    fmt.Printf("rămas în sursă: %q\n", rest)
}

Rezultat

"Universitatea"
rămas în sursă: " Alexandru Ioan Cuza din Iași"

Exemplul 2: Limită cu detectarea depășirii

package main

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

const maxComentariu = 20

func citesteComentariu(r io.Reader) (string, error) {
    date, err := io.ReadAll(io.LimitReader(r, maxComentariu+1))
    if err != nil {
        return "", err
    }
    if len(date) > maxComentariu {
        return "", errors.New("comentariu prea lung")
    }
    return string(date), nil
}

func main() {
    for _, text := range []string{"Livrare rapidă!", "Produsul a ajuns după trei săptămâni"} {
        c, err := citesteComentariu(strings.NewReader(text))
        fmt.Printf("%q %v\n", c, err)
    }
}

Rezultat

"Livrare rapidă!" <nil>
"" comentariu prea lung

Greșeli frecvente

  • Crezi că LimitReader dă eroare la depășire. Doar se oprește; datele sunt tăiate fără avertisment.

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ă).
  • io.NewSectionReader: Creează un Reader care vede doar o porțiune (de la off, n octeți) dintr-o sursă cu acces direct, ca un fișier.
  • io.Reader: Interfața pentru orice sursă de date din care se poate citi: fișiere, text, conexiuni, răspunsuri HTTP.