Ce face io.Pipe
io.Pipe leagă un cod care vrea un io.Writer de un cod care vrea un io.Reader, fără buffer intermediar: fiecare Write așteaptă până când datele sunt citite. De aceea scriitorul și cititorul trebuie să fie în goroutine diferite.
Scriitorul semnalează sfârșitul cu pw.Close() (cititorul primește io.EOF) sau o eroare cu pw.CloseWithError(err). Exemplu tipic: generezi JSON cu json.NewEncoder(pw) și îl trimiți direct ca corp al unei cereri HTTP, fără să-l construiești întâi în memorie.
Spre deosebire de os.Pipe, io.Pipe există doar în program și nu poate fi dat unui proces copil.
Ce returnează
Capătul de citire (*io.PipeReader) și capătul de scriere (*io.PipeWriter).
Exemple
Exemplul 1: Producător și consumator
package main
import (
"bufio"
"fmt"
"io"
)
func main() {
pr, pw := io.Pipe()
go func() {
defer pw.Close()
for i := 1; i <= 3; i++ {
fmt.Fprintf(pw, "comanda %d\n", 1040+i)
}
}()
s := bufio.NewScanner(pr)
for s.Scan() {
fmt.Println("procesez:", s.Text())
}
}
Rezultat
procesez: comanda 1041
procesez: comanda 1042
procesez: comanda 1043
Exemplul 2: JSON generat din mers
Encoder-ul scrie în pipe, iar celălalt capăt e citit ca un io.Reader (aici cu io.ReadAll, în practică de http.Post).
package main
import (
"encoding/json"
"fmt"
"io"
)
type Produs struct {
Nume string `json:"nume"`
Pret float64 `json:"pret"`
}
func main() {
pr, pw := io.Pipe()
go func() {
err := json.NewEncoder(pw).Encode([]Produs{{"carte", 45.5}, {"pix", 3}})
pw.CloseWithError(err)
}()
corp, err := io.ReadAll(pr)
fmt.Print(string(corp))
fmt.Println("eroare:", err)
}
Rezultat
[{"nume":"carte","pret":45.5},{"nume":"pix","pret":3}]
eroare: <nil>
Exemplul 3: Eroare transmisă cititorului
package main
import (
"errors"
"fmt"
"io"
)
func main() {
pr, pw := io.Pipe()
go func() {
pw.Write([]byte("date parțiale..."))
pw.CloseWithError(errors.New("conexiunea cu baza de date s-a pierdut"))
}()
date, err := io.ReadAll(pr)
fmt.Printf("%q\n", date)
fmt.Println("eroare:", err)
}
Rezultat
"date parțiale..."
eroare: conexiunea cu baza de date s-a pierdut
Greșeli frecvente
- Scrii și citești din pipe în aceeași goroutine.
Writeașteaptă un cititor care nu vine niciodată: programul se blochează („all goroutines are asleep – deadlock”). - Uiți
pw.Close(). Cititorul așteaptă la nesfârșit după ultimele date.
Comenzi înrudite
os.Pipe: Creează un pipe al sistemului de operare: ce scrii la un capăt (w) poți citi la celălalt (r).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.Copy: Copiază toate datele dintr-un Reader într-un Writer, pe bucăți, fără să le țină pe toate în memorie.