Allons-y programmes en ligne de commande avec Golang

Vue d'ensemble

La langue Go est une nouvelle langue passionnante qui gagne beaucoup de popularité pour une bonne raison. Dans ce didacticiel, vous apprendrez à écrire des programmes en ligne de commande avec Go. L'exemple de programme s'appelle multi-git et vous permet d'exécuter des commandes git sur plusieurs référentiels en même temps..

Introduction rapide à Go

Go est un langage open-source de type C créé sur Google par certains des pirates C et Unix d'origine, motivés par leur aversion pour le C ++. Cela se voit dans la conception de Go, qui a fait plusieurs choix peu orthodoxes tels que l’évitement de l’héritage, des modèles et des exceptions. Go est simple, fiable et efficace. Sa caractéristique la plus distinctive est son support explicite pour la programmation concurrente via des goroutines et des canaux..

Avant de commencer à disséquer le programme exemple, suivez le guide officiel pour vous préparer au développement de Go.

Go est un langage de programmation incroyablement puissant. Vous y apprendrez tout, de l'écriture de simples utilitaires à la construction de serveurs Web évolutifs et flexibles dans notre cours complet.

Le programme Multi-Git

Le programme multi-git est un programme Go simple mais utile. Si vous travaillez dans une équipe où la base de code est répartie sur plusieurs référentiels git, vous devez souvent effectuer des modifications sur plusieurs référentiels. C'est un problème parce que git n'a pas de concept de référentiels multiples. Tout tourne autour d'un référentiel unique. 

Cela devient particulièrement gênant si vous utilisez des branches. Si vous travaillez sur une fonctionnalité qui touche trois référentiels, vous devrez créer une branche de fonctionnalité dans chacun de ces référentiels, puis vous rappeler de les extraire, de les extraire, de les pousser et de les fusionner en même temps. Ce n'est pas anodin. Multi-git gère un ensemble de référentiels et vous permet d’opérer sur l’ensemble en même temps. Notez que la version actuelle de multi-git nécessite la création des branches individuellement, mais je peux ajouter cette fonctionnalité ultérieurement..

En explorant la façon dont multi-git est implémenté, vous en apprendrez beaucoup sur l'écriture de programmes en ligne de commande dans Go.

Forfaits et importations

Les programmes Go sont organisés en paquets. Le programme multi-git consiste en un seul fichier appelé main.go. En haut du fichier, le nom du package 'main' est spécifié, suivi d'une liste des importations. Les imports sont d'autres paquetages utilisés par multi-git.

package principal d'importation ("indicateur" "fmt" "journal" "os" "chaînes" "os / exec")

Par exemple, le paquetage fmt est utilisé pour des E / S formatées similaires à printf et scanf de C. Go prend en charge l’installation de paquets provenant de diverses sources via le va chercher commander. Lorsque vous installez des packages, ils se retrouvent dans un espace de noms sous le nom $ GOPATH variable d'environnement. Vous pouvez installer des packages à partir de diverses sources telles que GitHub, Bitbucket, Google code, Launchpad et même les services IBM DevOps via plusieurs formats de contrôle de version courants, tels que git, subversion, mercurial et bazaar..

Arguments de ligne de commande

Les arguments de ligne de commande sont l’une des formes les plus courantes de saisie des programmes. Ils sont faciles à utiliser, vous permettent d’exécuter et de configurer le programme sur une seule ligne et de prendre en charge l’analyse dans de nombreuses langues. Go les appelle "indicateurs" de ligne de commande et dispose du paquetage indicateur pour spécifier et analyser les arguments (ou les indicateurs) de ligne de commande. 

En règle générale, vous analysez les arguments de ligne de commande au début de votre programme et multi-git respecte cette convention. Le point d'entrée est le principale() une fonction. Les deux premières lignes définissent deux indicateurs appelés "command" et "ignoreErrors". Chaque indicateur a un nom, un type de données, une valeur par défaut et une chaîne d'aide. le flag.Parse () call analysera la ligne de commande réelle passée au programme et remplira les drapeaux définis.

func main () command: = flag.String ("commande", "", "La commande git") ignoreErrors: = flag.Bool ("ignore-errors", false, indicateur "Continuer à courir après l'erreur si vrai") .Parse ()

Il est également possible d’accéder à des arguments non définis via le flag.Args () une fonction. Ainsi, les drapeaux représentent des arguments prédéfinis et les "arguments" sont des arguments non traités. Les arguments non traités sont indexés sur 0.

Variables d'environnement

Les variables d’environnement sont une autre forme courante de configuration de programme. Lorsque vous utilisez des variables d'environnement, vous pouvez exécuter le même programme plusieurs fois dans le même environnement et toutes les exécutions utiliseront les mêmes variables d'environnement.. 

Multi-git utilise deux variables d’environnement: "MG_ROOT" et "MG_REPOS". Multi-git est conçu pour gérer un groupe de référentiels git ayant un répertoire parent commun. C'est "MG_ROOT". Les noms de référentiels sont spécifiés dans "MG_REPOS" en tant que chaîne séparée par des virgules. Pour lire la valeur d’une variable d’environnement, vous pouvez utiliser le os.Getenv () une fonction.

 // Obtention des pensions gérées à partir de variables d'environnement root: = os.Getenv ("MG_ROOT") si root [len (root) - 1]! = '/' Root + = "/" repo_names: = strings.Split (os .Getenv ("MG_REPOS"), ",")

Vérification de la liste de référentiels

Maintenant qu'il a trouvé le répertoire racine et les noms de tous les référentiels, multi-git vérifie que chaque référentiel existe sous root et qu'il s'agit bien d'un référentiel git. La vérification est aussi simple que de rechercher un sous-répertoire .git pour chaque répertoire de référentiel..

Tout d'abord, un tableau de chaînes nommé "repos" est défini. Ensuite, il parcourt tous les noms de référentiel et construit un chemin de référentiel en concaténant le répertoire racine et le nom du référentiel. Si la [os.Stat ()] () L'appel échoue pour le sous-répertoire .git, il enregistre l'erreur et se ferme. Sinon, le chemin du référentiel est ajouté au tableau de mise en pension..

 var repos [] string // Vérifie que tous les dépôts existent et sont en fait des dépôts git (ont un sous-répertoire .git) pour _, r: = plage "/.git") si err! = nil log.Fatal (err) repos = append (repos, chemin)

Go dispose d'une fonction unique de traitement des erreurs, dans laquelle les fonctions renvoient souvent une valeur de retour et un objet d'erreur. Découvrez comment os.Stat () renvoie deux valeurs. Dans ce cas, l'espace réservé "_" est utilisé pour conserver le résultat réel car vous vous souciez uniquement de l'erreur. Go est très strict et nécessite l'utilisation de variables nommées. Si vous n'envisagez pas d'utiliser une valeur, vous devez l'affecter à "_" pour éviter les erreurs de compilation..

Exécuter des commandes shell

À ce stade, vous avez votre liste de chemins de référentiels dans lesquels nous souhaitons exécuter la commande git. Comme vous vous en souvenez, nous avons reçu la ligne de commande git sous la forme d'un seul argument (indicateur) appelé "commande". Cela doit être divisé en un tableau de composants (commande git, sous-commande et options). La commande entière en tant que chaîne est également stockée à des fins d'affichage.

 // Découpe la commande git en composants (nécessaires à l'exécution) var git_components [] chaîne pour _, composant: = chaîne de caractères.Split (* commande, "") git_components = append (git_components, composant) command_string: = "git "+ * commande

Maintenant, vous êtes tous prêts à parcourir chaque référentiel et à exécuter la commande git dans chacun d'entre eux. La construction de boucle "for ... range" est à nouveau utilisée. Tout d'abord, multi-git modifie son répertoire de travail pour le référentiel cible actuel "r" et affiche la commande git. Ensuite, il exécute la commande en utilisant le exec.Command () fonction et imprime la sortie combinée (sortie standard et erreur standard). 

Enfin, il vérifie s'il y a eu une erreur lors de l'exécution. S'il y avait une erreur et le ignorer les erreurs flag est false, puis multi-git se sauve. Si vous ignorez éventuellement les erreurs, c'est que parfois, si les commandes échouent sur certains dépôts, c'est bien. Par exemple, si vous souhaitez extraire une branche appelée "fonctionnalité intéressante" sur tous les référentiels dotés de cette branche, vous ne vous inquiétez pas de l'échec de l'extraction sur des référentiels ne comportant pas cette branche..

 pour _, r: = range repos // Accédez au répertoire du référentiel os.Chdir (r); // Affiche la commande fmt.Printf ("[% s]% s \ n", r, chaîne_commande) // exécute la commande, err: = exec.Command ("git", git_components…) .CombinedOutput () / / Affiche le résultat fmt.Println (string (out)) // Supprime les erreurs éventuelles et PAS les ignorer si err! = Nil &&! * IgnoreErrors os.Exit (1) fmt.Println ("Terminé . ")

Conclusion

Go est un langage simple mais puissant. Il est conçu pour la programmation système à grande échelle, mais fonctionne également très bien pour les petits programmes en ligne de commande. La conception minimale de Go contraste fortement avec d'autres langages modernes tels que Scale et Rust, qui sont également très puissants et bien conçus, mais qui nécessitent une courbe d'apprentissage très abrupte. Je vous encourage à essayer Go et à expérimenter. C'est très amusant.