Уроки модуля (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 opens, reads everything into memory and closes. Идеально подходит до нескольких МБ; кроме того, потоковая передача лучше.
Открытие файлов для потоковой передачи
Для больших файлов или добавочного доступа откройте файл и закройте его с помощью 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[???])