io.TeeReader în Go

Returnează un Reader care, pe măsură ce citești din r, scrie aceiași octeți și în w.

Sintaxă
func TeeReader(r Reader, w Writer) Reader

Ce face io.TeeReader

io.TeeReader(r, w) se comportă ca r, dar fiecare bucată citită este scrisă și în w înainte să ți-o dea. Astfel „spionezi” datele care trec, fără să le citești de două ori.

Exemple: calculezi hash-ul unui fișier în timp ce îl decodezi, păstrezi o copie a corpului unei cereri HTTP pentru jurnal, numeri octeții citiți. Ce nu citești din TeeReader nu ajunge nici în w. Dacă scrierea în w dă eroare, citirea returnează acea eroare.

Parametri

Parametru Descriere
r Sursa.
w Unde se copiază datele citite.

Ce returnează

Un io.Reader.

Exemple

Exemplul 1: Decodare JSON și copie pentru jurnal

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "strings"
)

func main() {
    corp := strings.NewReader(`{"client":"Ana","total":249.9}`)
    var copie bytes.Buffer

    var comanda struct {
        Client string
        Total  float64
    }
    err := json.NewDecoder(io.TeeReader(corp, &copie)).Decode(&comanda)
    fmt.Printf("%+v %v\n", comanda, err)
    fmt.Println("corp primit:", copie.String())
}

Rezultat

{Client:Ana Total:249.9} <nil>
corp primit: {"client":"Ana","total":249.9}

Exemplul 2: Hash calculat în timpul citirii

package main

import (
    "bufio"
    "crypto/sha256"
    "fmt"
    "io"
    "strings"
)

func main() {
    fisier := strings.NewReader("Ana,Iași\nMihai,Cluj\nIoana,Brașov\n")
    h := sha256.New()

    s := bufio.NewScanner(io.TeeReader(fisier, h))
    randuri := 0
    for s.Scan() {
        randuri++
    }
    fmt.Println("rânduri:", randuri)
    fmt.Printf("sha256: %x\n", h.Sum(nil))
}

Rezultat

rânduri: 3
sha256: 167782adc5459f8c335e7f48ef8052310f77a07b6bdf37f45e74ed698b51ffec

Greșeli frecvente

  • Te aștepți ca w să conțină toată sursa, dar nu ai citit-o până la capăt. În w ajunge doar ce a fost citit.

Comenzi înrudite

  • io.MultiWriter: Creează un Writer care trimite fiecare scriere la toți Writer-ii dați, ca tee din Unix.
  • io.MultiReader: Leagă mai multe Reader-e unul după altul, ca și cum ar fi o singură sursă continuă.
  • io.Reader: Interfața pentru orice sursă de date din care se poate citi: fișiere, text, conexiuni, răspunsuri HTTP.
  • io.Copy: Copiază toate datele dintr-un Reader într-un Writer, pe bucăți, fără să le țină pe toate în memorie.