Module lessons (3/5)
`io` and `os`: files and streams
Reading and writing files and streams in Go revolves around two complementary packages: os (opening, creation, metadata, processes) and io (the Reader/Writer interfaces that abstract any byte source).
Reading and writing files: the shortcuts
For small or configuration files, a single call is enough:
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 opens, reads everything into memory and closes. Perfect up to a few MB; beyond that, streaming is better.
Opening files for streaming
For large files or incremental access, open the file and close it with defer:
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 opens in read-only. To write use os.Create (truncates if it exists) or os.OpenFile(path, flag, perm) with flags like os.O_APPEND | os.O_CREATE | os.O_WRONLY.
io.Reader and io.Writer: the universal interfaces
type Reader interface { Read(p []byte) (n int, err error) }
type Writer interface { Write(p []byte) (n int, err error) }Wherever the standard library accepts an io.Reader you can pass a file (*os.File), a string (strings.NewReader), a *bytes.Buffer, an HTTP response (resp.Body), a decompressor... The same goes for io.Writer.
// Copy from a Reader to a Writer (e.g. download → file).
n, err := io.Copy(dst, src)io.Copy is the workhorse for byte pipelines: it handles buffering and EOF correctly. io.ReadAll(r) reads everything until EOF into a []byte.
os.Args: CLI arguments
os.Args is a slice of strings: index 0 is the program name, from 1 on the actual arguments:
func main() {
if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "uso: prog <nome>")
os.Exit(1)
}
fmt.Println("ciao", os.Args[1])
}For more structured parsing (flags, defaults, help) use the flag package from the stdlib or external libraries like cobra.
os.Stdin, os.Stdout, os.Stderr
These are three global *os.Files: wherever an io.Reader or io.Writer is accepted you can pass them.
fmt.Fprintln(os.Stderr, "log diagnostico")
io.Copy(os.Stdout, os.Stdin) // echoExercises
Print the first command-line argument (os.Args[1]). If it is missing, print 'manca argomento' and return.
Solution available after 3 attempts
Write the string 'ciao' to the file 'out.txt' with os.WriteFile (permissions 0644). Handle the error.
Solution available after 3 attempts
What is the index of the PROGRAM NAME in os.Args?
fmt.Println(os.Args[???])