De la idea a la utilidad CLI en Go: escribimos, compilamos, desplegamos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Por qué Go es el lenguaje ideal para utilidades CLI?

\n\n

Imagínese: necesita escribir una herramienta que se ejecute en la consola, procese archivos, acceda a API o simplemente automatice tareas rutinarias. Puede elegir Python, Node.js o Bash. Pero si la velocidad, el tamaño del binario y la facilidad de distribución son críticos, su elección son las utilidades CLI en Go.

\n\n

Go se compila en un único binario estático. Sin dependencias, sin "¿tienes Python 3.8 instalado?". Descárgalo y ejecútalo. Esto hace que las herramientas Golang CLI sean el estándar de facto en el mundo DevOps (recuerde Docker, Kubernetes, Hugo; todos están escritos en Go).

\n\n

En este artículo no solo hablaremos de teoría. Crearemos desde cero una utilidad de consola en Go real que analizará JSON, trabajará con HTTP y mostrará tablas bonitas. Aprenderá cómo estructurar un proyecto, manejar errores y compilar para cualquier plataforma.

\n\n

Configuración del entorno y estructura del proyecto

\n\n

Antes de escribir código, asegúrese de tener Go instalado (versión 1.21+). Verificarlo es sencillo:

\n\n
go version
\n\n

Creemos un directorio para nuestro proyecto. Llamaremos a la utilidad json2table; leerá JSON desde stdin o un archivo y mostrará los datos en forma de tabla.

\n\n
mkdir json2table\ncd json2table\ngo mod init github.com/su-usuario/json2table
\n\n

La estructura del proyecto será clásica para el desarrollo en Go:

\n\n
    \n
  • main.go — punto de entrada
  • \n
  • internal/ — lógica interna (análisis, salida)
  • \n
  • cmd/ — código para manejar comandos (si usamos Cobra)
  • \n
\n\n

Comenzaremos de forma simple, sin frameworks, y luego añadiremos banderas y ayuda.

\n\n

Escribimos el núcleo de la utilidad: análisis de JSON y salida de tabla

\n\n

Cree el archivo internal/parser.go. Aquí analizaremos JSON y lo convertiremos en una estructura.

\n\n
package internal\n\nimport (\n    "encoding/json"\n    "fmt"\n    "io"\n)\n\n// Record representa una fila de la tabla\ntype Record map[string]interface{}\n\n// ParseJSON lee JSON desde un reader y devuelve un slice de registros\nfunc ParseJSON(r io.Reader) ([]Record, error) {\n    var data []Record\n    decoder := json.NewDecoder(r)\n    if err := decoder.Decode(&data); err != nil {\n        return nil, fmt.Errorf("error al analizar JSON: %w", err)\n    }\n    return data, nil\n}
\n\n

Ahora crearemos internal/table.go para la salida formateada:

\n\n
package internal\n\nimport (\n    "fmt"\n    "strings"\n    "text/tabwriter"\n    "os"\n)\n\n// PrintTable muestra los registros en forma de tabla con alineación\nfunc PrintTable(records []Record) {\n    if len(records) == 0 {\n        fmt.Println("No hay datos para mostrar")\n        return\n    }\n\n    // Recopilamos todas las claves únicas (encabezados de columna)\n    headers := make([]string, 0)\n    seen := make(map[string]bool)\n    for _, rec := range records {\n        for key := range rec {\n            if !seen[key] {\n                headers = append(headers, key)\n                seen[key] = true\n            }\n        }\n    }\n\n    // Usamos tabwriter para una salida bonita\n    w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)\n\n    // Encabezado\n    fmt.Fprintln(w, strings.Join(headers, "\\t"))\n\n    // Separador\n    sep := make([]string, len(headers))\n    for i, h := range headers {\n        sep[i] = strings.Repeat("-", len(h))\n    }\n    fmt.Fprintln(w, strings.Join(sep, "\\t"))\n\n    // Datos\n    for _, rec := range records {\n        row := make([]string, len(headers))\n        for i, h := range headers {\n            if val, ok := rec[h]; ok {\n                row[i] = fmt.Sprintf("%v", val)\n            } else {\n                row[i] = ""\n            }\n        }\n        fmt.Fprintln(w, strings.Join(row, "\\t"))\n    }\n\n    w.Flush()\n}
\n\n

Montamos todo en main.

Blogs

Book Recommendations