¿Por qué trabajar con archivos en Go no da miedo, sino que es interesante?
\n\nCuando abrí por primera vez la documentación del paquete os en Go, pensé que me esperaba una aburrida enumeración de llamadas al sistema. Pero, profundizando un poco, me di cuenta: trabajar con archivos y el sistema de archivos en Go no es solo leer bytes. Es una herramienta poderosa que te da control total sobre los datos, ya sean archivos de configuración, registros, binarios o bases de datos enteras en CSV.
Go fue creado para la programación de sistemas, por lo que sus autores (Ken Thompson, Rob Pike y otros) integraron el trabajo con archivos directamente en el núcleo del lenguaje. Sin dependencias externas, solo la biblioteca estándar, que funciona de forma rápida y predecible. En este artículo, cubriremos todos los escenarios: desde la lectura simple de un archivo hasta el recorrido recursivo de directorios y el procesamiento en flujo de grandes datos.
\n\nSi escribes en Go y quieres trabajar con confianza con el sistema de archivos, estás en el lugar correcto. ¡Vamos allá!
\n\nFundamentos: abrir, leer, cerrar
\n\nEl primer paso es abrir un archivo. En Go, esto se hace con la función os.Open(). Devuelve un puntero al archivo y un error. Los errores en Go no son excepciones, sino valores. Siempre hay que verificarlos.
package main\n\nimport (\n "fmt"\n "os"\n)\n\nfunc main() {\n file, err := os.Open("example.txt")\n if err != nil {\n fmt.Println("Error al abrir el archivo:", err)\n return\n }\n defer file.Close() // obligatorio cerrar el archivo\n\n // Leer el contenido\n buf := make([]byte, 1024)\n n, err := file.Read(buf)\n if err != nil {\n fmt.Println("Error al leer:", err)\n return\n }\n fmt.Printf("Leídos %d bytes: %s\\n", n, string(buf[:n]))\n}\n\n\nObserva defer file.Close(). Es un modismo de Go: la llamada diferida garantiza que el archivo se cierre incluso en caso de pánico o retorno anticipado. Olvidar cerrar un archivo es una mala práctica que provoca fugas de descriptores.
Lectura de todo el archivo en una línea
\n\nSi el archivo es pequeño (hasta unos pocos megabytes), puedes usar os.ReadFile() (reemplazó al obsoleto ioutil.ReadFile). Es útil para configuraciones o datos de texto.
data, err := os.ReadFile("config.yaml")\nif err != nil {\n log.Fatal(err)\n}\nfmt.Println(string(data))\n\n\nLa función abre, lee y cierra el archivo por sí sola. Pero recuerda: para archivos grandes, este enfoque es peligroso: cargarás todo el archivo en la memoria.
\n\nEscritura en archivos: crear y añadir
\n\nPara escribir, usa os.Create() (crea un archivo nuevo o trunca uno existente) y os.OpenFile() para una configuración más precisa (por ejemplo, añadir al final).
// Crear archivo\nfile, err := os.Create("output.txt")\nif err != nil {\n panic(err)\n}\ndefer file.Close()\n\n// Escribir una cadena\n_, err = file.WriteString("¡Hola, archivos Go!\\n")\nif err != nil {\n panic(err)\n}\n\n// Escribir bytes\nbytes := []byte("Escritura de un slice de bytes\\n")\n_, err = file.Write(bytes)\nif err != nil {\n panic(err)\n}\n\n\nPara añadir datos al final de un archivo existente, usa las banderas:
\n\nfile, err := os.OpenFile("log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\nif err != nil {\n log.Fatal(err)\n}\ndefer file.Close()\n\nfile.WriteString("Nueva entrada en el registro\\n")\n\n\nLa bandera os.O_APPEND garantiza que los datos se añadan al final, no sobrescriban el inicio.
Trabajo con directorios: crear, eliminar, recorrer
\n\nEl sistema de archivos no solo son archivos, sino también carpetas. Go proporciona funciones convenientes para trabajar con directorios.
\n\nCrear y eliminar carpetas
\n\n// Crear una carpeta\nerr := os.Mkdir("newdir", 0755)\nif err != nil {\n log.Fatal(err)\n}\n\n// Crear carpetas anidadas (como mkdir -p)\nerr = os.MkdirAll("path/to/nested/dir", 0755)\nif err != nil {\n log.Fatal(err)\