Menu

go run, go build ou go install : compiler et exécuter du Go

Ce que font go run, go build et go install, comment Go nomme le binaire, comment compiler pour une autre plateforme avec GOOS et GOARCH, et les vérifications go fmt et go vet à lancer avant de committer.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

go run compile et exécute un programme en une étape sans garder de binaire. go build compile et laisse un exécutable dans le répertoire courant. go install compile et place l'exécutable dans $HOME/go/bin. Les trois compilent en code machine natif ; aucun n'interprète quoi que ce soit.

CommandeCompileExécuteGarde un binaireOù va le binaire
go run .ouiouinonrépertoire temporaire, supprimé ensuite
go buildouinonouirépertoire courant (ou -o path)
go installouinonoui$GOBIN, sinon $GOPATH/bin

Le programme ci-dessous est celui utilisé dans les exemples de cette page. L'éditeur l'exécute comme le ferait go run.

go run

go run prend un package (généralement ., le répertoire courant) ou une liste de fichiers .go :

go run .
go run main.go
go run ./cmd/server

Tout ce qui suit le package est transmis à votre programme comme arguments :

go run . --port 8080 verbose
version: dev
built for: linux/amd64
args: [--port 8080 verbose]

Préférez go run . à go run main.go. Nommer un fichier ne compile que ce fichier, donc dès que le package a un second fichier, les fonctions qui y sont définies sont signalées comme undefined. La page sur les packages et les imports traite cette erreur en détail.

go run exécute aussi un programme distant à une version précise sans l'installer, ce qui est pratique pour les générateurs de code :

go run golang.org/x/tools/cmd/stringer@v0.30.0 -type=Color

go build

go build compile le package du répertoire courant. Pour un package main, il écrit un exécutable ; pour un package de bibliothèque, il compile, signale les erreurs et jette le résultat.

go mod init example.com/hello
go build
ls
go.mod  hello  main.go

Le nom du binaire suit ces règles :

Vous lancezNom du binaire
go build dans le module example.com/hellohello
go build ./cmd/serverserver
go build main.gomain (d'après le premier fichier)
go build -o bin/app .bin/app
n'importe lequel des cas ci-dessus avec GOOS=windowsmême nom plus .exe

Deux autres formes que vous utiliserez tout le temps :

go build ./...      # compile every package in the module
go vet ./...        # static checks, covered below

./... signifie « ce répertoire et tous ceux qui sont en dessous ». go build ./... avec plusieurs packages main n'écrit aucun binaire ; c'est une vérification rapide que tout compile.

Flags de build utiles

FlagCe qu'il fait
-o namefichier ou répertoire de sortie
-vaffiche le nom des packages au fur et à mesure de la compilation
-racecompile avec le détecteur de data races (plus lent, binaire plus gros ; pour les tests)
-trimpathretire les chemins du système de fichiers local du binaire, pour des builds reproductibles
-ldflags "-s -w"retire la table des symboles et les infos de débogage DWARF, ce qui réduit le binaire
-ldflags "-X main.version=1.4.0"définit une variable string à l'édition de liens
-tags nameinclut les fichiers protégés par une contrainte //go:build name

Le flag -X est la façon dont la plupart des projets Go inscrivent une version dans le binaire. Il ne fonctionne que sur des variables string au niveau du package (pas sur des constantes) :

go build -o app -ldflags "-X main.version=1.4.0" .
./app
version: 1.4.0
built for: linux/amd64
args: []

Le binaire enregistre aussi les versions de ses modules et, depuis Go 1.18, le commit VCS à partir duquel il a été compilé. go version -m ./app les affiche, et un programme peut les lire avec runtime/debug.ReadBuildInfo.

go install

go install compile exactement comme go build puis déplace l'exécutable dans $GOBIN, ou dans $GOPATH/bin quand GOBIN n'est pas défini (par défaut $HOME/go/bin) :

go install .
go env GOPATH

Son usage le plus courant est d'installer des outils écrits en Go. Avec @version, il installe un programme sans toucher à votre go.mod :

go install golang.org/x/tools/gopls@latest
go install honnef.co/go/tools/cmd/staticcheck@latest

Si le shell ne trouve pas un outil ensuite, c'est que $HOME/go/bin n'est pas dans votre PATH. Ajoutez export PATH=$PATH:$(go env GOPATH)/bin au profil de votre shell.

Compilation croisée avec GOOS et GOARCH

Go peut compiler pour un autre système d'exploitation ou un autre processeur depuis n'importe quelle machine, sans chaîne d'outils supplémentaire. Définissez deux variables d'environnement pour la commande de build :

GOOS=linux GOARCH=amd64 go build -o app-linux-amd64 .
GOOS=linux GOARCH=arm64 go build -o app-linux-arm64 .
GOOS=darwin GOARCH=arm64 go build -o app-macos .
GOOS=windows GOARCH=amd64 go build -o app.exe .

Dans PowerShell, les variables d'environnement se définissent autrement :

$env:GOOS = "linux"; $env:GOARCH = "amd64"; go build -o app-linux .

Les paires les plus courantes :

GOOSGOARCHCible
linuxamd64la plupart des serveurs et conteneurs
linuxarm64AWS Graviton, Raspberry Pi avec un OS 64 bits
darwinarm64Mac Apple Silicon
darwinamd64Mac Intel
windowsamd64Windows 64 bits
jswasmWebAssembly dans un navigateur

go tool dist list affiche toutes les paires prises en charge (48 dans Go 1.24).

La compilation croisée n'est aussi simple que pour du code Go pur. Un package qui utilise cgo (du code C, par exemple certains drivers SQLite) a besoin d'un compilateur C croisé pour la cible. En compilation croisée, cgo est désactivé par défaut, et définir explicitement CGO_ENABLED=0 vous donne aussi un binaire Linux entièrement statique, ce qu'il vous faut dans une image de conteneur minimale scratch ou distroless.

go fmt et go vet

Deux vérifications ont leur place dans chaque flux de travail, et en CI.

go fmt réécrit les fichiers dans le style officiel unique : tabulations, champs alignés, espacements normalisés. C'est une surcouche de gofmt -l -w :

go fmt ./...
gofmt -l .     # list files that are not formatted; empty output means clean

go vet signale du code qui compile mais qui est presque certainement faux. Les incohérences de format de Printf sont le cas classique :

package main

import "fmt"

func main() {
	count := 3
	fmt.Printf("%s items\n", count)
}
go vet ./...
# example.com/hello
# [example.com/hello]
./main.go:7:2: fmt.Printf format %s has arg count of wrong type int

Le programme compile et affiche %!s(int=3) items, exactement le genre de bug que vet est là pour détecter. D'autres vérifications de vet repèrent la copie d'un sync.Mutex par valeur, le code inaccessible, les struct tags à la syntaxe invalide, et une context.CancelFunc jamais appelée. go test lance automatiquement une partie de ces vérifications ; go build n'en lance aucune.

Autres sous-commandes de go

CommandeRôle
go test ./...lancer les tests
go mod tidyajouter les dépendances manquantes et retirer celles qui sont inutilisées
go get pkg@versionajouter ou changer une dépendance
go clean -cachevider le cache de build
go envafficher la configuration de Go
go doc fmt.Printlnafficher la documentation dans le terminal
go list -m alllister tous les modules du build

Pourquoi le deuxième build est rapide

Go met en cache les packages compilés dans le cache de build (go env GOCACHE). Un rebuild ne recompile que les packages dont le source ou les dépendances ont changé, donc go run . sur un projet inchangé démarre presque instantanément. Si un build se comporte bizarrement après un changement de version de Go ou de variables d'environnement, go clean -cache le vide ; vous devriez rarement en avoir besoin.

Questions fréquentes

Quelle est la différence entre go run et go build ?

go run compile le programme dans un répertoire temporaire, l'exécute, puis jette le binaire. go build compile le programme et écrit le binaire dans le répertoire courant pour que vous puissiez le relancer ou le copier ailleurs. Utilisez go run pendant le développement et go build quand vous avez besoin de l'exécutable.

Comment définir le nom du fichier de sortie de go build ?

Utilisez -o : go build -o myapp . écrit myapp (sous Windows, écrivez vous-même -o myapp.exe). Sans -o, go build nomme le binaire d'après le dernier élément du chemin d'import du package, ou d'après le premier fichier quand vous passez des fichiers .go, et ajoute .exe quand la cible est Windows.

Comment compiler du Go pour Linux ou Windows depuis une autre machine ?

Définissez GOOS et GOARCH pour le build : GOOS=linux GOARCH=amd64 go build -o app-linux . ou GOOS=windows GOARCH=amd64 go build . (qui produit un .exe). Aucune chaîne d'outils supplémentaire n'est nécessaire pour du code Go pur. go tool dist list affiche toutes les paires prises en charge.

Où go install place-t-il le binaire ?

Dans $GOBIN s'il est défini, sinon dans $GOPATH/bin, qui vaut $HOME/go/bin par défaut. Ajoutez ce répertoire à votre PATH pour lancer les outils installés par leur nom. go install example.com/tool@latest installe un outil sans l'ajouter à votre module.

go build lance-t-il go vet ?

Non. go build ne fait que compiler. go test lance automatiquement une partie des vérifications de go vet, mais pour l'ensemble complet lancez go vet ./... vous-même, typiquement en CI à côté de gofmt -l ..

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER