Vai al contenuto
eLearner.app
Modulo 8 · Lezione 3 di 538/50 nel corso~14 min
Lezioni del modulo (3/5)

`io` e `os`: file e stream

Lettura e scrittura di file e stream in Go ruotano attorno a due pacchetti complementari: os (apertura, creazione, metadati, processi) e io (le interfacce Reader/Writer che astraggono qualsiasi sorgente di byte).

Leggere e scrivere file: le scorciatoie

Per file piccoli o di configurazione, una sola chiamata basta:

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

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

os.ReadFile apre, legge tutto in memoria e chiude. Perfetto fino a qualche MB; oltre, meglio fare streaming.

Aprire file per streaming

Per file grandi o accesso incrementale apri il file e chiudilo con defer:

Go
f, err := os.Open("big.txt")        // sola lettura
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 apre in sola lettura. Per scrivere usa os.Create (tronca se esiste) o os.OpenFile(path, flag, perm) con flag come os.O_APPEND | os.O_CREATE | os.O_WRONLY.

io.Reader e io.Writer: le interfacce universali

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

Ovunque la libreria standard accetti io.Reader puoi passare un file (*os.File), una stringa (strings.NewReader), uno *bytes.Buffer, una risposta HTTP (resp.Body), un decompressore... La stessa cosa per io.Writer.

Go
// Copia da un Reader a un Writer (es. download → file).
n, err := io.Copy(dst, src)

io.Copy è il workhorse per pipeline di byte: gestisce buffer e EOF in modo corretto. io.ReadAll(r) legge tutto fino a EOF in []byte.

os.Args: argomenti CLI

os.Args è uno slice di stringhe: indice 0 è il nome del programma, da 1 in poi gli argomenti veri:

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

Per parsing più strutturato (flag, default, help) usa il pacchetto flag della stdlib o librerie esterne come cobra.

os.Stdin, os.Stdout, os.Stderr

Sono tre *os.File globali: ovunque accetti un io.Reader o io.Writer puoi passarli.

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

Esercizi

Esercizio#go.m8.l3.e1
Tentativi: 0Caricamento…

Stampa il primo argomento da riga di comando (os.Args[1]). Se manca, stampa 'manca argomento' e ritorna.

Caricamento editor…

Soluzione disponibile dopo 3 tentativi

Esercizio#go.m8.l3.e2
Tentativi: 0Caricamento…

Scrivi la stringa 'ciao' nel file 'out.txt' con os.WriteFile (permessi 0644). Gestisci l'errore.

Caricamento editor…

Soluzione disponibile dopo 3 tentativi

Quiz#go.m8.l3.e3
Pronto

Qual è l'indice del NOME DEL PROGRAMMA in os.Args?

Go
fmt.Println(os.Args[???])
Opzioni di risposta