os, io, bufio & path/filepath
A E/S de arquivos e streams em Go organiza pequenas interfaces em pipelines compostos.
Busque em todas as páginas da documentação
A E/S de arquivos e streams em Go organiza pequenas interfaces em pipelines compostos.
os fala com o sistema de arquivos, io define o movimento de bytes, bufio reduz a sobrecarga de chamadas de sistema, e path/filepath constrói caminhos portáteis.
A maioria dos programas Go lê configurações, serve uploads ou canaliza dados entre processos.
A biblioteca padrão modela tudo isso como implementações de io.Reader e io.Writer.
os.Open retorna um *os.File que você pode passar para io.Copy, bufio.NewScanner ou json.NewDecoder.
Ferramentas multiplataforma nunca devem codificar / ou \ em hardcode; filepath.Join escolhe o separador correto.
Cartão de receita de referência rápida - pronto para copiar e colar.
path := filepath.Join("data", "input.txt")
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()
var out bytes.Buffer
if _, err := io.Copy(&out, f); err != nil {
return err
}Quando usar isso:
bufio.Scanner.package main
import (
"bufio"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
func copyFiltered(srcPath, dstPath, prefix string) (int, error) {
srcPath = filepath.Clean(srcPath)
dstPath = filepath.Clean(dstPath)
src, err := os.Open(srcPath)
if err != nil {
return 0, fmt.Errorf("abrir src: %w", err)
}
defer src.Close()
if err := os.MkdirAll(filepath.Dir(dstPath), 0o755); err != nil {
return 0, fmt.Errorf("mkdir: %w", err)
}
dst, err := os.Create(dstPath)
if err != nil {
return 0, fmt.Errorf("criar dst: %w", err)
}
defer func() {
if cerr := dst.Close(); cerr != nil && err == nil {
err = cerr
}
}()
scanner := bufio.NewScanner(src)
writer := bufio.NewWriter(dst)
defer writer.Flush()
lines := 0
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, prefix) {
if _, err := writer.WriteString(line + "\n"); err != nil {
return lines, err
}
lines++
}
}
if err := scanner.Err(); err != nil {
return lines, err
}
return lines, nil
}
func main() {
n, err := copyFiltered("input.log", filepath.Join("out", "filtered.log"), "ERR")
if err != nil {
panic(err)
}
fmt.Println("linhas escritas:", n)
}O que isso demonstra:
filepath.Clean e filepath.Join para montagem segura de caminhos.os.MkdirAll antes de criar arquivos de saída aninhados.bufio.Scanner para iteração de linha e bufio.Writer para escritas em lote.io.Copy lê de qualquer Reader e escreve em qualquer Writer usando um pool de buffers interno.*os.File mapeiam para descritores de arquivo do SO; os deslocamentos são rastreados por manipulador.bufio.Reader e bufio.Writer envolvem streams para agrupar chamadas de sistema.filepath opera em caminhos como strings; ele não acessa o sistema de arquivos (use os para isso).| Pacote | Responsabilidade | Pontos de entrada típicos |
|---|---|---|
os | Arquivos, env, processo, argumentos | Open, ReadFile, WriteFile, Getenv |
io | Contratos e utilitários de stream | Copy, ReadAll, LimitReader, Pipe |
bufio | Buffering e escaneamento | NewScanner, NewReader, NewWriter |
path/filepath | Operações de caminho específicas do SO | Join, Clean, Walk, Rel |
// Prefira io.Copy a loops Read manuais para canalização.
// Limite uploads para evitar exaustão de memória:
limited := io.LimitReader(r.Body, 1<<20) // Limite de 1 MiB
// Percorre árvores de diretórios de forma portátil:
filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
// processa o arquivo
return nil
})defer f.Close() e propague erros de fechamento em escritores.path em vez de path/filepath - path é para caminhos com barras normais semelhantes a URLs, não para caminhos do sistema de arquivos Windows. Correção: importe path/filepath para caminhos do SO.Scanner.Err() - O loop termina silenciosamente em erros de E/S. Correção: verifique sc.Err() após for sc.Scan().sc.Buffer(make([]byte, 0, 64*1024), maxToken).Read preenche o buffer - Read pode retornar n < len(buf) com erro nil. Correção: repita até io.EOF ou use io.ReadFull.os.Stat e depois os.Open - O arquivo pode mudar entre as verificações. Correção: abra primeiro e depois valide o conteúdo ou use bloqueios de arquivo quando necessário.| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
os.ReadFile / os.WriteFile | Arquivos pequenos e limitados | Transmitindo uploads ou logs grandes |
mmap via syscall ou terceiros | Leitura sem cópia de arquivos enormes | Portabilidade e simplicidade importam mais |
embed.FS | Empacotar ativos estáticos no binário | Caminhos fornecidos pelo usuário no disco |
Abstrações afero ou io/fs | Testar o sistema de arquivos sem disco | Ferramentas CLI simples apenas com arquivos reais |
io.Reader é uma interface com um método Read.
*os.File implementa io.Reader (e io.Writer) para streams baseados em sistema de arquivos.
Funções que aceitam io.Reader funcionam com arquivos, corpos de rede, strings e buffers igualmente.
Use bufio quando você realiza muitas leituras ou escritas pequenas e deseja menos chamadas de sistema.
Use leituras diretas quando você já tem buffers grandes ou dados mapeados em memória.
Join insere o separador correto para o SO e limpa elementos redundantes.
Concatenação manual falha no Windows e introduz bugs de barra dupla.
Clean simplifica segmentos . e .., mas não valida a confiança.
Valide as raízes de entrada do usuário separadamente antes de abrir arquivos.
data, err := os.ReadFile(path) então string(data).
Para arquivos grandes, transmita com bufio.Scanner ou io.Copy em vez disso.
Use o mínimo necessário; 0o600 para configuração privada, 0o644 para artefatos legíveis por todos.
Nunca use 0777 como padrão em código de aplicativo.
Sim.
Chame sc.Split com uma SplitFunc personalizada ou use bufio.NewReader com ReadString.
Leia uma vez em um buffer ou use io.TeeReader para copiar bytes para um escritor secundário enquanto lê.
Não há um Reader de distribuição embutido.
Erros de fechamento são ignorados, a menos que você os atribua em um closure adiado.
Escritores, especialmente, precisam de verificações de erro de fechamento para descarregar buffers.
Ao aceitar streams de entrada não confiáveis (uploads HTTP, corpos RPC) para limitar o uso de memória e CPU.
Combine com verificações de tamanho máximo antes de io.ReadAll.
Sim, para diretórios de scratch que você criou.
Nunca aponte RemoveAll para caminhos fornecidos pelo usuário sem validar que eles permanecem sob uma raiz esperada.
filepath.WalkDir passa os.DirEntry sem chamadas Stat extras, reduzindo chamadas de sistema em árvores grandes.
Prefira WalkDir em código novo.
Versões da Stack: Esta página foi escrita para Go 1.26.x (GC padrão Green Tea, go fix modernizers - verifique o patch na compilação), chi (mais recente - verifique na compilação), gin (mais recente - verifique na compilação), echo (mais recente - verifique na compilação), google.golang.org/grpc (mais recente - verifique na compilação), sigs.k8s.io/controller-runtime (mais recente - verifique na compilação), kubebuilder (mais recente - verifique na compilação), tinygo (mais recente - verifique os alvos de placa na compilação), wazero (mais recente - verifique na compilação) e golangci-lint (mais recente - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026