Direct naar de hoofdinhoud
Module 8 · Les 3 van 538/50 in de cursus~14 min
Modulelessen (3/5)

`io` en `os`: bestanden en streams

Het lezen en schrijven van bestanden en streams in Go draait om twee complementaire pakketten: os (openen, creëren, metadata, processen) en io (de Reader/Writer interfaces die elke bytebron abstraheren).

Bestanden lezen en schrijven: de snelkoppelingen

Voor kleine of configuratiebestanden is één enkele oproep voldoende:

Go
data, err := os.ReadFile("input.txt")        // returns []byte
if err != nil {
    return err
}
fmt.Println(string(data))

err = os.WriteFile("out.txt", []byte("ciao"), 0644)

os.ReadFile opent, leest alles in het geheugen en sluit. Perfect tot een paar MB; verder is streaming beter.

Bestanden openen voor streaming

Voor grote bestanden of incrementele toegang opent u het bestand en sluit u het met defer:

Go
f, err := os.Open("big.txt")        // read-only
if err != nil {
    return err
}
defer f.Close()

buf := make([]byte, 4096)
for {
    n, err := f.Read(buf)
    if n > 0 {
        process(buf[:n])
    }
    if err == io.EOF {
        break
    }
    if err != nil {
        return err
    }
}

os.Open wordt geopend in alleen-lezen. Om te schrijven gebruik je os.Create (wordt afgekapt als dit bestaat) of os.OpenFile(path, flag, perm) met vlaggen zoals os.O_APPEND | os.O_CREATE | os.O_WRONLY.

io.Reader en io.Writer: de universele interfaces

Go
type Reader interface { Read(p []byte) (n int, err error) }
type Writer interface { Write(p []byte) (n int, err error) }

Overal waar de standaardbibliotheek een io.Reader accepteert, kunt u een bestand (*os.File), een string (strings.NewReader), een *bytes.Buffer, een HTTP-antwoord (resp.Body), een decompressor doorgeven... Hetzelfde geldt voor io.Writer.

Go
// Copy from a Reader to a Writer (e.g. download → file).
n, err := io.Copy(dst, src)

io.Copy is het werkpaard voor bytepijplijnen: het verwerkt buffering en EOF correct. io.ReadAll(r) leest alles tot EOF in een []byte.

os.Args: CLI-argumenten

os.Args is een stukje tekenreeks: index 0 is de programmanaam, vanaf 1 tot de feitelijke argumenten:

Go
func main() {
    if len(os.Args) < 2 {
        fmt.Fprintln(os.Stderr, "uso: prog <nome>")
        os.Exit(1)
    }
    fmt.Println("ciao", os.Args[1])
}

Voor meer gestructureerde parsering (vlaggen, standaardinstellingen, help) gebruikt u het pakket flag uit de stdlib of externe bibliotheken zoals cobra.

os.Stdin, os.Stdout, os.Stderr

Dit zijn drie globale *os.Files: overal waar een io.Reader of io.Writer wordt geaccepteerd, kun je ze doorgeven.

Go
fmt.Fprintln(os.Stderr, "log diagnostico")
io.Copy(os.Stdout, os.Stdin)  // echo

Oefeningen

Oefening#go.m8.l3.e1
Pogingen: 0Laden…

Druk het eerste opdrachtregelargument af (os.Args[1]). Als het ontbreekt, drukt u 'manca argomento' af en keert u terug.

Editor laden…

Oplossing beschikbaar na 3 pogingen

Oefening#go.m8.l3.e2
Pogingen: 0Laden…

Schrijf de string 'ciao' naar het bestand 'out.txt' met os.WriteFile (rechten 0644). Behandel de fout.

Editor laden…

Oplossing beschikbaar na 3 pogingen

Quiz#go.m8.l3.e3
Klaar

Wat is de index van de PROGRAMMANAAM in os.Args?

Go
fmt.Println(os.Args[???])
Antwoordmogelijkheden