Listado de directorios en Go: de lo simple a lo complejo
\n\nTrabajar con el sistema de archivos es una de las tareas básicas de cualquier lenguaje de programación. En Go está implementado de manera tan elegante que incluso una operación tan rutinaria como list directory in Go se convierte en una aventura fascinante. Si alguna vez te has preguntado: "¿Cómo obtengo una lista de archivos en una carpeta en Go?" — has llegado al lugar indicado. Hoy analizaremos todas las formas posibles, desde la salida simple hasta el recorrido recursivo con filtrado.
\n\n¿Por qué este tema es tan popular en Stack Overflow? Porque Go ofrece varios enfoques a la vez, y elegir el correcto es la mitad del éxito. Veremos el clásico os.ReadDir, el obsoleto ioutil.ReadDir (pero aún se puede encontrar en proyectos antiguos), y el potente filepath.Walk para recorrido recursivo. ¡Allá vamos!
1. Listado más simple: os.ReadDir
\n\nA partir de Go 1.16, el paquete os recibió un nuevo método ReadDir, que se convirtió en el estándar de facto. Devuelve un slice de objetos os.DirEntry — descripciones ligeras de archivos y carpetas. Así es como se ve:
package main\n\nimport (\n "fmt"\n "os"\n "log"\n)\n\nfunc main() {\n // Leemos el contenido del directorio actual\n entries, err := os.ReadDir(".")\n if err != nil {\n log.Fatal(err)\n }\n\n fmt.Println("Contenido de la carpeta actual:")\n for _, entry := range entries {\n fmt.Printf("- %s (directorio: %v)\\n", entry.Name(), entry.IsDir())\n }\n}\n\n\nEste código mostrará todos los archivos y carpetas en el directorio actual. Ten en cuenta: os.ReadDir no lee subcarpetas — solo el primer nivel. Si necesitas list directory in Go recursivamente, sigue leyendo.
2. ioutil.ReadDir: antiguo, pero familiar
\n\nAntes de la versión Go 1.16, todos usaban ioutil.ReadDir. Devuelve []os.FileInfo — una estructura más pesada con información completa del archivo (tamaño, permisos, fecha de modificación). Aunque el método está marcado como deprecated, aún puedes encontrarlo en código heredado:
package main\n\nimport (\n "fmt"\n "io/ioutil"\n "log"\n)\n\nfunc main() {\n files, err := ioutil.ReadDir("./mydir")\n if err != nil {\n log.Fatal(err)\n }\n\n fmt.Println("Archivos en mydir (método antiguo):")\n for _, file := range files {\n fmt.Printf("Nombre: %s, Tamaño: %d bytes\\n", file.Name(), file.Size())\n }\n}\n\n\nLa principal diferencia: ioutil.ReadDir ordena el resultado por nombre de archivo (como ls), mientras que os.ReadDir no lo hace. Si el orden es importante, usa sort.Slice u ordenación manual.
3. Recorrido recursivo con filepath.Walk
\n\nCuando necesitas recorrer todas las subcarpetas, filepath.Walk viene al rescate. Esta función recorre el árbol de directorios, llamando a un callback para cada elemento encontrado. Ideal para copias de seguridad, búsqueda de archivos o análisis de la estructura del proyecto:
package main\n\nimport (\n "fmt"\n "os"\n "path/filepath"\n)\n\nfunc main() {\n root := "./myproject"\n err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {\n if err != nil {\n return err\n }\n fmt.Printf("Encontrado: %s (tamaño: %d)\\n", path, info.Size())\n return nil\n })\n if err != nil {\n fmt.Println("Error en el recorrido:", err)\n }\n}\n\n\nUn detalle importante: filepath.Walk sigue enlaces simbólicos y puede entrar en un bucle infinito si hay enlaces cíclicos. Para producción usa filepath.WalkDir (Go 1.16+) — es más ligero y seguro.
4. Filtrado: solo archivos .go o solo carpetas
\n\nA menudo no se necesita todo, sino solo ciertos tipos de archivos. Implementemos el filtrado con strings.HasSuffix y la verificación IsDir()