Trabajo con el sistema de archivos en Go: para principiantes
Go (Golang) es un lenguaje compilado moderno que se destaca por su simplicidad, rendimiento y herramientas integradas. Una de las tareas clave de cualquier desarrollador backend es la interacción con el sistema de archivos: lectura de configuraciones, escritura de registros, creación de archivos y directorios temporales. En este artículo, analizaremos las operaciones básicas con archivos y carpetas en Go, comenzando desde lo más básico. El material está diseñado para principiantes, por lo que cada paso irá acompañado de ejemplos de código claros.
Paquetes principales para trabajar con archivos
En la biblioteca estándar de Go hay dos paquetes principales para trabajar con el sistema de archivos:
os— trabajo de bajo nivel con archivos, carpetas, permisos y procesos.io/ioutil(obsoleto en Go 1.16, pero aún se encuentra) — funciones convenientes para leer/escribir archivos completos.io— interfaces para entrada/salida por flujo.bufio— lectura/escritura con búfer (útil para archivos grandes).
A partir de Go 1.16, se recomienda usar funciones del paquete os (os.ReadFile, os.WriteFile) en lugar de ioutil. Nos basaremos en el enfoque moderno.
Lectura de archivos
La forma más sencilla de leer un archivo pequeño por completo es usar os.ReadFile. Devuelve un slice de bytes y un error.
package main
import ( "fmt" "os")
func main() { // Lectura completa del archivo data, err := os.ReadFile("example.txt") if err != nil { fmt.Println("Error al leer el archivo:", err) return } fmt.Println("Contenido del archivo:") fmt.Println(string(data))}Si el archivo es grande (por ejemplo, un archivo de registro de cientos de megabytes), es mejor leerlo línea por línea o en bloques usando bufio.Scanner:
package main
import ( "bufio" "fmt" "os")
func main() { file, err := os.Open("bigfile.log") if err != nil { fmt.Println("Error al abrir el archivo:", err) return } defer file.Close() // cerramos el archivo obligatoriamente
scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() fmt.Println(line) // procesamos la línea }
if err := scanner.Err(); err != nil { fmt.Println("Error de escaneo:", err) }}Tenga en cuenta defer file.Close() — esto garantiza que el archivo se cerrará después de que finalice la función, incluso si ocurre un error.
Escritura en archivos
Para escribir datos en un archivo, use os.WriteFile (crea/sobrescribe el archivo) o os.Create + Write (para una escritura más flexible).
package main
import ( "fmt" "os")
func main() { // Escritura simple de una cadena en un archivo text := "¡Hola, mundo!Segunda línea." err := os.WriteFile("output.txt", []byte(text), 0644) if err != nil { fmt.Println("Error de escritura:", err) return } fmt.Println("Archivo escrito exitosamente")}El parámetro 0644 son los permisos de acceso al estilo Unix (el propietario puede leer/escribir, los demás solo leer).
Si necesita agregar datos al final del archivo (append), use os.OpenFile con la bandera os.O_APPEND:
package main
import ( "fmt" "os")
func main() { file, err := os.OpenFile("log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { fmt.Println("Error al abrir el archivo:", err) return } defer file.Close()
_, err = file.WriteString("Nueva entrada en el registro") if err != nil { fmt.Println("Error de escritura:", err) }}