io.ReadWriter în Go

Interfața pentru tipurile din care se poate și citi, și în care se poate scrie (Reader + Writer).

Sintaxă
type ReadWriter interface {
    Reader
    Writer
}

Ce face io.ReadWriter

io.ReadWriter este o interfață compusă: un tip o implementează dacă are atât Read, cât și Write. Exemple: *os.File, *bytes.Buffer, o conexiune de rețea (net.Conn).

Pachetul io are mai multe asemenea combinații: ReadCloser, WriteCloser, ReadWriteCloser, ReadSeeker. Cere în funcțiile tale cea mai mică interfață de care ai nevoie.

Ce returnează

Nu se aplică (este o interfață).

Exemple

Exemplul 1: Un buffer ca ReadWriter

package main

import (
    "bytes"
    "fmt"
    "io"
)

func ecou(rw io.ReadWriter, mesaj string) string {
    io.WriteString(rw, mesaj)
    date, _ := io.ReadAll(rw)
    return string(date)
}

func main() {
    var buf bytes.Buffer
    fmt.Println(ecou(&buf, "Salut, Ana!"))
}

Rezultat

Salut, Ana!

Exemplul 2: Un protocol simplu peste orice ReadWriter

Aceeași funcție ar merge și pe o conexiune TCP; aici o testăm cu un buffer.

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "io"
)

func trimiteComanda(rw io.ReadWriter, cmd string) (string, error) {
    if _, err := fmt.Fprintf(rw, "%s\n", cmd); err != nil {
        return "", err
    }
    return bufio.NewReader(rw).ReadString('\n')
}

func main() {
    var conexiune bytes.Buffer // în realitate: net.Conn
    raspuns, err := trimiteComanda(&conexiune, "PING")
    fmt.Printf("%q %v\n", raspuns, err)
}

Rezultat

"PING\n" <nil>

Greșeli frecvente

  • Ceri io.ReadWriter într-o funcție care doar citește. Cere io.Reader; mai multe tipuri vor putea fi folosite.

Comenzi înrudite

  • io.Reader: Interfața pentru orice sursă de date din care se poate citi: fișiere, text, conexiuni, răspunsuri HTTP.
  • io.Writer: Interfața pentru orice destinație în care se pot scrie octeți: fișiere, ecran, buffer-e, răspunsuri HTTP.
  • io.Closer: Interfața pentru orice resursă care trebuie închisă după folosire (fișiere, conexiuni, corpuri HTTP).