Comment écrire du code Go ?

Cet article est une traduction de la page How to Write Go Code ? (en anglais sur le site du projet Go).

Introduction

Ce document explique comment développer un paquet Go simple. C'est également une introduction à l'outil go, le standard pour chercher, récupérer, compiler et installer les paquets et les commandes Go.

L'outil go requiert que vous organisiez votre code d'une certaine manière. Veuillez donc lire attentivement ce document. Car il explique comment profiter de votre environnement de développement Go en toute simplicité.

Organisation du code

Espaces de travail

L'outil go est conçu pour fonctionner avec du code source ouvert et maintenu dans des dépôts publics. Bien que vous n'ayez pas besoin de rendre public votre code, le modèle d'installation de votre environnement de développement est la même, que vous publiiez votre code publiquement ou pas.

Le code Go doit être stocké dans un espace de travail. Un espace de travail est une arborescence de répertoires avec trois dossiers à sa racine :

  • src contient le les fichiers source Go organisés en paquets (un paquet par répertoire),
  • pkg contient les objets binaires des paquets, et
  • bin contient les commandes (des fichiers exécutables).

L'outil go compile les fichiers sources des paquets et installe les binaires résultant de cette compilation dans les répertoires pkg et bin.

Le sous-répertoire src contient les dossiers synchronisés avec les gestionnaires de code source (tels que Git ou Mercurial) qui gèrent le développement du code source d'un ou plusieurs paquets.

Pour vous donner une idée de ce à quoi ressemble un espace de travail dans la pratique, voici un exemple :

bin/
    streak                         # exécutable de la commande "streak"
    todo                           # exécutable de la commande "todo"
pkg/
    linux_amd64/
        code.google.com/p/goauth2/
            oauth.a                # objet binaire d'un paquet
        github.com/nf/todo/
            task.a                 # objet binaire d'un paquet
src/
    code.google.com/p/goauth2/
        .hg/                       # Méta-données d'un dépôt mercurial
        oauth/
            oauth.go               # code source d'un package
            oauth_test.go          # code source du test d'un package
    github.com/nf/
        streak/
            .git/                  # Méta-données d'un dépôt git
            oauth.go               # code source de la commande "oauth"
            streak.go              # code source de la commande "streak"
        todo/
            .git/                  # git repository metadata
            task/
                task.go            # un des fichiers du code source d'un paquet
            todo.go                # code source de la commande "todo"

Cet espace de travail comprend trois dépôts (goauth2, streak, et todo) qui contiennent deux commandes (streak et todo) et deux bibliothèques (oauth et task).

Les commandes et les bibliothèques sont compilées à partir de différents emplacements de code source. Nous verrons cela plus en détail dans le paragraphe « Noms de paquet ».

La variable d'environnement GOPATH

La variable d'environnement GOPATH contient l'emplacement de votre espace de travail. C'est probablement la seule variable d'environnement que vous aurez besoin de définir pour développer du code Go.

Pour commencer, créez un répertoire qui contiendra votre espace de travail et définissez la variable d'environnement GOPATH en fonction de l'emplacement du répertoire. Votre espace de travail peut être stocké n'importe où, mais nous utiliserons $HOME/go dans cet article. Veuillez noter que l'espace de travail ne doit pas être le répertoire d'installation de Go.

$ mkdir $HOME/go
$ export GOPATH=$HOME/go

Pour que cela soit plus pratique, vous devriez ajouter le sous-répertoire bin (de votre espace de travail) à la variable PATH :

$ export PATH=$PATH:$GOPATH/bin

Chemins de paquet

Les paquets de la bibliothèque standard ont des chemins courts tels que "fmt" ou "net/http". Pour vos propres paquets, vous devez choisir une base de chemin qui ne provoquera pas de conflit éventuel avec les futurs ajouts à la bibliothèque standard (ndt: Évitez par exemple une base avec un nom générique tel que "collection" ou "gui". Les discussions sur la liste officielle découragent également l'emploi de noms de paquets commençant par "go").

Si vous conservez votre code dans un gestionnaire de code source, alors vous devriez utiliser la racine de ce dépôt en tant que base du chemin d'accès aux répertoires de vos paquets. Par exemple, si vous avez un compte Github intitulé github.com/user, cela devrait être la base du chemin d'accès.

Notez que vous n'avez pas besoin de publier votre code sur un gestionnaire de code source externe afin de pouvoir le compiler. C'est simplement une bonne habitude si vous souhaitez le rendre public un jour. Dans la pratique, vous pouvez choisir un chemin d'accès complètement arbitraire du moment qu'il est unique par rapport à la bibliothèque standard et à l'écosystème Go.

Nous utiliserons github.com/user comme base du chemin d'accès. Créez un répertoire dans votre espace de travail afin d'y stocker votre code source :

$ mkdir -p $GOPATH/src/github.com/user

Votre premier programme

Pour compiler et exécuter un simple programme, commencez par choisir un chemin de paquet (nous utiliserons github.com/user/hello), puis créez le répertoire correspondant à l'intérieur de votre espace de travail :

$ mkdir $GOPATH/src/github.com/user/hello

Créez ensuite un fichier nommé hello.go dans ce répertoire. Ce fichier contiendra le code Go suivant :

package main

import "fmt"

func main() {
  fmt.Printf("Hello, world.\n")
}

Vous pouvez maintenant compiler et installer ce programme avec l'outil go :

$ go install github.com/user/hello

Notez que vous pouvez lancer cette commande depuis n'importe quel emplacement de votre système. L'outil go trouve le code source en cherchant le paquet github.com/user/hello dans l'espace de travail spécifié par la variable d'environnement GOPATH.

Vous pouvez aussi omettre le chemin du paquet dans le cas où vous lancez la commande go install depuis le répertoire du paquet :

$ cd $GOPATH/src/github.com/user/hello
$ go install

Cette commande compile la commande hello en produisant un binaire exécutable. Elle installe ensuite ce fichier binaire dans le répertoire bin de l'espace de travail (le nom du fichier est hello ou hello.exe sous Windows). Dans notre exemple, le chemin complet serait $GOPATH/bin/hello, qui est en fait $HOME/go/bin/hello.

L'outil go n'affichera quelque chose seulement si une erreur survient. Donc, si la commande n'affiche rien, c'est qu'elle s'est exécutée sans erreur.

Vous pouvez maintenant lancer le programme en tapant son chemin complet dans la console :

$ $GOPATH/bin/hello
Hello, world.

Ou, comme vous avez ajouté $GOPATH/bin à votre variable d'environnement PATH, tapez simplement le nom de l'exécutable :

$ hello
Hello, world.

Si vous utilisez un gestionnaire de code source, cela serait maintenant le bon moment pour créer le dépôt, ajouter les fichiers et acquitter les changements. Encore une fois, cette étape est optionnelle : vous n'avez pas besoin d'un gestionnaire de code source pour développer en Go.

$ cd $GOPATH/src/github.com/user/hello
$ git init
Initialized empty Git repository in /home/user/go/src/github.com/user/hello/.git/
$ git add hello.go
$ git commit -m "initial commit"
[master (root-commit) 0b4507d] initial commit
 1 file changed, 1 insertion(+)
  create mode 100644 hello.go

Votre première bibliothèque

Écrivons une bibliothèque et utilisons-la dans le programme hello.

On répète que la première étape consiste à choisir un chemin de paquet (nous utiliserons github.com/user/newmath), puis il faut créer le répertoire correspondant :

$ mkdir $GOPATH/src/github.com/user/newmath

Ensuite, créons un fichier nommé sqrt.go dans ce répertoire et avec ce contenu.

package newmath

// Sqrt retourne une approximation de la racine carré de x.
func Sqrt(x float64) float64 {
	z := 1.0
	for i := 0; i < 1000; i++ {
		z -= (z*z - x) / (2 * z)
	}
	return z
}

Maintenant, testons la compilation de ce paquet avec la commande go build :

$ go build github.com/user/newmath

Ou, si vous travaillez dans le répertoire des sources du paquet, tapez simplement :

$ go build

Cela ne produira aucun fichier en sortie. Pour ce faire, vous devez utiliser la commande go install qui placera l'objet binaire résultant de la compilation précédente dans le répertoire pkg de votre espace de travail.

Après la confirmation du fait que le paquet newmath est compilable, modifiez le fichier source hello.go (qui est dans le répertoire $GOPATH/src/github.com/user/hello) afin de l'utiliser :

package main

import (
	"fmt"
	"github.com/user/newmath"
)

func main() {
	fmt.Printf("Hello, world.  Sqrt(2) = %v\n", newmath.Sqrt(2))
}

Lorsque l'outil go installe un paquet ou un binaire, il installe aussi toutes ses dépendances. Donc, lorsque vous installez le programme hello :

$ go install github.com/user/hello

Le paquet newmath sera également installé automatiquement.

En exécutant la nouvelle version du programme, vous devriez voir un nombre s'afficher :

$ hello
Hello, world.  Sqrt(2) = 1.414213562373095

Après les étapes ci-dessus, votre espace de travail devrait ressembler à ça :

bin/
    hello              # exécutable de la commande
pkg/
    linux_amd64/       # reflet de votre système d'exploitation et du type de CPU
        github.com/user/
            newmath.a  # objet binaire du paquet
src/
    github.com/user/
        hello/
            hello.go   # fichier source de la commande
        newmath/
            sqrt.go    # fichier source du paquet

Vous remarquerez que la commande go install a placé l'objet binaire newmath.a dans un répertoire sous pkg/linux_amd64 (répertoire dont le nom reflète le nom du répertoire du code source). Cela permet aux futures invocations de l'outil go de trouver l'objet binaire du paquet et ainsi, d'éviter de recompiler inutilement le paquet. Le nom linux_amd64 facilite la compilation croisée et reflètera le système d'exploitation et l'architecture du CPU.

Les exécutables Go sont liés statiquement ; les objets binaires des paquets dont ils dépendent n'ont donc pas besoin d'être présents pour lancer les programmes Go.

Noms de paquet

La première instruction dans un fichier source Go doit être :

package nom

nom est le nom par défaut du paquet pour la directive d'import du paquet (tous les fichiers source d'un paquet doivent contenir le même nom).

En Go, la convention est que le nom du paquet est le dernier élément du chemin d'import : le paquet importé en tant que "crypto/rot13" devrait s'appeler rot13.

Les exécutables d'une commande doivent toujours utiliser la directive package main.

Il n'y a aucune exigence spécifiant que les noms des paquets doivent être uniques parmi tous les paquets liés dans un seul binaire, mais seulement que les chemins d'import (leurs noms complets de fichier) soient uniques.

Voyez l'article Effective Go (en anglais sur le blog officiel) pour en savoir plus sur les conventions de nom en Go.

Test

Go contient un framework de test minimal composé de la commande go test et du paquet testing.

Vous pouvez écrire un test en créant un fichier avec un nom terminant par _test.go. Ce fichier contiendra des fonctions nommées TestXXX et une signature func (t *testing.T). Le framework de test exécute chacune de ces fonctions ; si la fonction appelle une fonction d'échec telle que t.Error ou t.Fail, alors le test est considéré comme ayant échoué.

Ajoutez un test au paquet newmath en créant le fichier $GOPATH/src/github.com/user/newmath/sqrt_test.go. Ce fichier contiendra le code ci-dessous :

package newmath

import "testing"

func TestSqrt(t *testing.T) {
	const in, out = 4, 2
	if x := Sqrt(in); x != out {
		t.Errorf("Sqrt(%v) = %v, want %v", in, x, out)
	}
}

Lancez ensuite le test avec la commande go test :

$ go test github.com/user/newmath
ok  	github.com/user/newmath 0.165s

Comme toujours, si vous lancez l'outil depuis le répertoire du paquet, vous pouvez omettre le chemin du paquet :

$ go test
ok  	github.com/user/newmath 0.165s

La commande go help test et la documentation du paquet "testing" permet d'en savoir plus sur les possibilités (ndt: à propos des Benchmark et du code d'exemple).

Paquets tiers

Un chemin d'import peut décrire comment obtenir le code source d'un paquet en utilisant un gestionnaire de code source tel que Git ou Mercurial. L'outil go utilise cette propriété pour récupérer automatiquement des paquets depuis des dépôts externes. En l'occurrence, les exemples décrits dans ce document sont aussi stockés dans un dépôt externe hébergé par Google Code : code.google.com/p/go.example. Si vous incluez l'URL de ce dépôt dans le chemin d'import du paquet, go get le récupérera, le compilera et l'installera automatiquement :

$ go get code.google.com/p/go.example/hello
$ $GOPATH/bin/hello
Hello, world.  Sqrt(2) = 1.414213562373095

Si le paquet voulu n'est pas présent dans l'espace de travail, go get le copiera dans l'emplacement désigné par la variable d'environnement GOPATH (si le paquet existe déjà, go get ne le téléchargera pas et se comportera comme la commande go install).

Après avoir exécuté la commande go get ci-dessus, l'espace de travail devrait ressembler à ça :

bin/
    hello                 # exécutable de la commande
pkg/
    linux_amd64/
        code.google.com/p/go.example/
            newmath.a     # objet binaire du paquet
        github.com/user/
            newmath.a     # objet binaire du paquet
src/
    code.google.com/p/go.example/
        hello/
            hello.go      # fichier source de la commande
        newmath/
            sqrt.go       # fichier source du paquet
            sqrt_test.go  # fichier source du test de sqrt.go
    github.com/user/
        hello/
            hello.go      # fichier source de la commande
        newmath/
            sqrt.go       # fichier source du paquet
            sqrt_test.go  # fichier source du test de sqrt.go

La commande hello hébergé sur le gestionnaire de code source Google Code dépend du paquet newmath — présent dans le même répertoire. L'import dans le fichier hello.go utilise la même convention de chemin d'import. Donc la commande go get est capable de localiser et d'installer le paquet dépendant.

import "code.google.com/p/go.example/newmath"

Cette convention est la manière la plus facile de rendre vos paquets Go disponibles et utilisables par autrui. Le wiki Go (en anglais) et le site godoc.org (en anglais) fournissent des listes de projets Go externes et importables en suivant les instructions de cet article.

Pour plus d'information sur l'utilisation des dépôts externes avec l'outil go, consultez l'aide ou tapez go help importpath.

À faire ensuite

Vous pouvez souscrire à la liste de diffusion golang-announce (en anglais) afin d'être notifié lorsqu'une nouvelle version stable de Go est publiée.

Vous pouvez lire l'article Effective Go (en anglais) pour des astuces pour écrire un code Go clair et mettant en œuvre les bonnes pratiques.

Suivez la visite A Tour of Go (en anglais) pour apprendre les bonnes bases du langage.

Visitez la page de documentation (en anglais) pour un ensemble d'articles entrant dans le détail du langage Go, des ses bibliothèques et outils.

Obtenir de l'aide

À la date de rédaction de cet article, il existe peu de ressources en français. Cependant, il y a beaucoup de moyens d'obtenir de l'aide si vous parlez anglais.

Pour de l'aide en temps réel, demandez aux Gophers du canal #go-nuts, sur le serveur d'IRC de Freenode.

La liste de diffusion du langage Go est Go Nuts.

Signalez les défauts sur le gestionnaire de défauts de Go.


Portrait de Benjamin BALET
Benjamin BALET
Consultant APM

Retrouvez mes cooordonées

Benjamin BALET sur viadeo






Vous aimerez aussi

Les lois de la réflexion

Une traduction du blog officiel de golang expliquant le mécanisme de la réflexion en Go.   Lire »

Gobs le format natif d'échange de données en Go

Traduction d'un article du blog officiel expliquant comment échanger des données entre deux programmes golang grâce à un format natif   Lire »

Comment gérer efficacement les erreurs en golang ?

Préconisations officielles pour la gestion des erreurs dans un programme golang. Cet article complète les explications sur panic, defer et recover   Lire »

Le modèle mémoire du runtime et du langage go

Traduction d'une partie des spécifications officielles du langage go, cet article explique comment go gère la mémoire.   Lire »

Tests unitaires automatisés et couverture de test en go

Comment obtenir un rapport sur la couverture du code par les tests unitaires en golang ? Un exemple de code et de cas de test.   Lire »

Commentaires

Soyez le premier à commenter cet article

Publier un commentaires

Tous les commentaires sont soumis à modération. Les balises HTML sont pour la plupart autorisées. Les liens contextuels et intéressants sont en follow.

(requis)
(requis)
(requis, mais non publié)
(recommandé si vous souhaitez être publié)