os.Pipe în Go

Creează un pipe al sistemului de operare: ce scrii la un capăt (w) poți citi la celălalt (r).

Sintaxă
func Pipe() (r *File, w *File, err error)

Ce face os.Pipe

os.Pipe returnează două fișiere legate: w pentru scriere și r pentru citire. Datele scrise în w apar, în aceeași ordine, la r. Citirea așteaptă până vin date sau până se închide w (atunci primește io.EOF).

Spre deosebire de io.Pipe, care există doar în memoria programului, os.Pipe este un pipe real al sistemului. Îl poți da unui proces copil ca intrare sau ieșire (cmd.Stdin, cmd.Stdout) sau îl poți folosi ca să capturezi ce scrie programul tău pe os.Stdout.

Ce returnează

Capătul de citire, capătul de scriere și nil, sau o eroare. Închide ambele capete când nu mai ai nevoie de ele.

Exemple

Exemplul 1: Scriere într-o goroutine, citire în main

w.Close() semnalează sfârșitul datelor; fără el, io.ReadAll ar aștepta la nesfârșit.

package main

import (
    "fmt"
    "io"
    "os"
)

func main() {
    r, w, err := os.Pipe()
    if err != nil {
        fmt.Println("eroare:", err)
        return
    }
    go func() {
        defer w.Close()
        for _, oras := range []string{"Iași", "Cluj", "Timișoara"} {
            fmt.Fprintln(w, oras)
        }
    }()

    date, _ := io.ReadAll(r)
    r.Close()
    fmt.Print(string(date))
}

Rezultat

Iași
Cluj
Timișoara

Exemplul 2: Capturarea a ce scrie fmt.Println

Înlocuim temporar os.Stdout cu capătul de scriere, apoi citim ce s-a scris.

package main

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

func salut(nume string) {
    fmt.Println("Bună ziua,", nume)
}

func main() {
    original := os.Stdout
    r, w, _ := os.Pipe()
    os.Stdout = w

    salut("Ana")

    w.Close()
    os.Stdout = original
    capturat, _ := io.ReadAll(r)
    fmt.Printf("funcția a scris: %q\n", strings.TrimSpace(string(capturat)))
}

Rezultat

funcția a scris: "Bună ziua, Ana"

Greșeli frecvente

  • Uiți să închizi capătul de scriere. Cititorul nu primește niciodată io.EOF și programul se blochează.
  • Scrii mult în pipe în aceeași goroutine care citește mai târziu. Pipe-ul are un buffer mic (de obicei 64 KB); când se umple, scrierea se blochează. Scrie și citește în goroutine diferite.

Comenzi înrudite

  • io.Pipe: Creează un pipe în memorie: ce scrie o goroutine la capătul Writer citește alta la capătul Reader.
  • os.IsTimeout: Spune dacă o eroare înseamnă că a expirat timpul de așteptare (timeout) al unei operații.
  • exec.Cmd.StdoutPipe: Returnează un Reader legat de ieșirea comenzii, ca să citești rezultatul pe măsură ce apare.
  • io.ReadAll: Citește tot ce oferă un Reader, până la final, și returnează datele ca slice de octeți.