Trabalhando com o sistema de arquivos em Go: na prática
\n\nTrabalhar com o sistema de arquivos é uma das tarefas básicas de qualquer aplicação servidora. A linguagem Go (Golang) fornece um conjunto de ferramentas poderoso e elegante para ler, escrever, excluir e gerenciar arquivos e diretórios. Neste artigo, vamos explorar exemplos práticos de trabalho com arquivos em Go, utilizando os pacotes padrão os, io/ioutil (até Go 1.16) e io. Você aprenderá como gerenciar dados no disco de forma eficiente, tratar erros e escrever código limpo.
1. Fundamentos: abrir, ler e escrever arquivos
\n\nVamos começar com as operações mais comuns. Para abrir um arquivo, utiliza-se a função os.OpenFile ou os wrappers mais simples os.Create e os.Open. Vejamos um exemplo de leitura de um arquivo inteiro para a memória:
package main\n\nimport (\n "fmt"\n "os"\n)\n\nfunc main() {\n // Lendo o arquivo inteiro (antes do Go 1.16 usávamos ioutil.ReadFile)\n data, err := os.ReadFile("example.txt")\n if err != nil {\n fmt.Println("Erro ao ler o arquivo:", err)\n return\n }\n fmt.Println("Conteúdo do arquivo:")\n fmt.Println(string(data))\n}\n\n\nPara escrever dados em um arquivo, use os.WriteFile:
package main\n\nimport (\n "os"\n)\n\nfunc main() {\n content := []byte("Olá, mundo Go!\\nSegunda linha.")\n err := os.WriteFile("output.txt", content, 0644)\n if err != nil {\n panic(err)\n }\n // O arquivo output.txt foi criado e contém nosso texto\n}\n\n\nSe você precisar adicionar dados ao final de um arquivo, use as flags:
\n\nfile, err := os.OpenFile("log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\nif err != nil {\n panic(err)\n}\ndefer file.Close()\n\nif _, err := file.WriteString("Nova entrada no log\\n"); err != nil {\n panic(err)\n}\n\n\n2. Trabalhando com diretórios: criação, exclusão e navegação
\n\nGerenciar pastas é uma tarefa igualmente importante. Você pode criar um novo diretório com os.Mkdir (uma pasta) ou os.MkdirAll (recursivamente, como mkdir -p):
package main\n\nimport (\n "fmt"\n "os"\n)\n\nfunc main() {\n // Criando uma única pasta\n err := os.Mkdir("data", 0755)\n if err != nil {\n fmt.Println("Erro ao criar a pasta:", err)\n }\n\n // Criando recursivamente uma estrutura aninhada\n err = os.MkdirAll("data/subdir/logs", 0755)\n if err != nil {\n fmt.Println("Erro:", err)\n }\n}\n\n\nPara navegar por um diretório, você pode usar a função os.ReadDir (substituta do ioutil.ReadDir):
entries, err := os.ReadDir(".")\nif err != nil {\n panic(err)\n}\n\nfor _, entry := range entries {\n fmt.Printf("Nome: %s, É pasta: %t\\n", entry.Name(), entry.IsDir())\n}\n\n\nE para navegar recursivamente por todos os arquivos e pastas, use filepath.Walk do pacote path/filepath:
package main\n\nimport (\n "fmt"\n "os"\n "path/filepath"\n)\n\nfunc main() {\n err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {\n if err != nil {\n return err\n }\n fmt.Println(path)\n return nil\n })\n if err != nil {\n fmt.Println("Erro na navegação:", err)\n }\n}\n\n\nA exclusão de arquivos e pastas é feita com as funções os.Remove e os.RemoveAll:
// Excluir um único arquivo ou pasta vazia\nos.Remove("temp.txt")\n\n// Excluir uma pasta com todo o seu conteúdo (análogo ao rm -rf)\nos.RemoveAll("data")\n\n\n3. Técnicas avançadas: entrada/saída com buffer e trabalho com arquivos temporários
\n\nPara arquivos grandes, não é eficiente ler todo o conteúdo para a memória. Use leitura com buffer utilizando bufio:
package main\n\nimport (\n "bufio"\n "