Pourquoi Go est le langage idéal pour les utilitaires CLI ?
\n\nImaginez : vous devez écrire un outil qui s'exécutera dans la console, traitera des fichiers, interrogera des API ou simplement automatisera des tâches répétitives. Vous pouvez choisir Python, Node.js ou Bash. Mais si la vitesse, la taille du binaire et la simplicité de distribution sont critiques — votre choix est l'utilitaire CLI en Go.
\n\nGo se compile en un seul binaire statique. Aucune dépendance, pas de « vous avez Python 3.8 d'installé ? ». Téléchargé, exécuté. Cela fait des outils CLI Golang le standard de facto dans le monde DevOps (rappelez-vous Docker, Kubernetes, Hugo — tous écrits en Go).
\n\nDans cet article, nous ne parlerons pas seulement de théorie. Nous allons créer de zéro un véritable utilitaire console en Go, qui analysera du JSON, travaillera avec HTTP et affichera de beaux tableaux. Vous apprendrez à structurer un projet, gérer les erreurs et compiler pour n'importe quelle plateforme.
\n\nConfiguration de l'environnement et structure du projet
\n\nAvant d'écrire du code, assurez-vous d'avoir Go installé (version 1.21+). Vérifiez simplement :
\n\ngo version\n\nCréons un répertoire pour notre projet. Nommons l'utilitaire json2table — il lira du JSON depuis stdin ou un fichier et affichera les données sous forme de tableau.
mkdir json2table\ncd json2table\ngo mod init github.com/votre-nom-utilisateur/json2table\n\nLa structure du projet sera classique pour le développement en Go :
\n\n- \n
main.go— point d'entrée \n internal/— logique interne (analyse, affichage) \n cmd/— code pour le traitement des commandes (si nous utilisons Cobra) \n
Nous commencerons simplement, sans frameworks, puis nous ajouterons des flags et de l'aide.
\n\nÉcrire le cœur de l'utilitaire : analyse JSON et affichage du tableau
\n\nCréez le fichier internal/parser.go. Ici, nous analyserons le JSON et le transformerons en structure.
package internal\n\nimport (\n "encoding/json"\n "fmt"\n "io"\n)\n\n// Record représente une ligne du tableau\ntype Record map[string]interface{}\n\n// ParseJSON lit le JSON depuis un reader et retourne une slice d'enregistrements\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("erreur d'analyse JSON : %w", err)\n }\n return data, nil\n}\n\nCréons maintenant internal/table.go pour l'affichage formaté :
package internal\n\nimport (\n "fmt"\n "strings"\n "text/tabwriter"\n "os"\n)\n\n// PrintTable affiche les enregistrements sous forme de tableau aligné\nfunc PrintTable(records []Record) {\n if len(records) == 0 {\n fmt.Println("Aucune donnée à afficher")\n return\n }\n\n // Collecte toutes les clés uniques (en-têtes de colonnes)\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 // Utilisation de tabwriter pour un bel affichage\n w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)\n\n // En-tête\n fmt.Fprintln(w, strings.Join(headers, "\\t"))\n\n // Séparateur\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 // Données\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