Модульні уроки (3/5)
`io` і `os`: файли та потоки
Читання та запис файлів і потоків у Go обертається навколо двох додаткових пакетів: os (відкриття, створення, метадані, процеси) і io (інтерфейси Reader/Writer, які абстрагують будь-яке джерело байтів).
Читання та запис файлів: ярлики
Для невеликих або конфігураційних файлів достатньо одного виклику:
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 відкривається, читає все в пам'ять і закривається. Ідеально до кількох МБ; крім того, потокове передавання краще.
Відкриття файлів для потокового передавання
Для великих файлів або інкрементального доступу відкрийте файл і закрийте його за допомогою 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 відкривається лише для читання. Для запису використовуйте os.Create (урізається, якщо він існує) або os.OpenFile(path, flag, perm) з такими прапорцями, як os.O_APPEND | os.O_CREATE | os.O_WRONLY.
io.Reader та io.Writer: універсальні інтерфейси
type Reader interface { Read(p []byte) (n int, err error) }
type Writer interface { Write(p []byte) (n int, err error) }Скрізь, де стандартна бібліотека приймає io.Reader, ви можете передати файл (*os.File), рядок (strings.NewReader), *bytes.Buffer, відповідь HTTP (resp.Body), декомпресор... Те саме стосується io.Writer.
// Copy from a Reader to a Writer (e.g. download → file).
n, err := io.Copy(dst, src)io.Copy — це робоча конячка для байтових конвеєрів: він правильно обробляє буферизацію та EOF. io.ReadAll(r) читає все до EOF у []byte.
os.Args: аргументи CLI
os.Args — фрагмент рядків: індекс 0 — це назва програми, починаючи з 1 і закінчуючи фактичними аргументами:
func main() {
if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "uso: prog <nome>")
os.Exit(1)
}
fmt.Println("ciao", os.Args[1])
}Для більш структурованого аналізу (прапорці, значення за замовчуванням, довідка) використовуйте пакет flag із stdlib або зовнішні бібліотеки, такі як cobra.
os.Stdin, os.Stdout, os.Stderr
Це три глобальні *os.File: усюди, де прийнято io.Reader або io.Writer, ви можете їх передати.
fmt.Fprintln(os.Stderr, "log diagnostico")
io.Copy(os.Stdout, os.Stdin) // echoвправи
Вивести перший аргумент командного рядка (os.Args[1]). Якщо його немає, надрукуйте «manca argomento» та поверніть.
Рішення доступне після 3 спроб
Запишіть рядок "ciao" у файл "out.txt" за допомогою os.WriteFile (дозволи 0644). Виправте помилку.
Рішення доступне після 3 спроб
Що таке індекс НАЗВИ ПРОГРАМИ в os.Args?
fmt.Println(os.Args[???])