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.
| Commande | Compile | Exécute | Garde un binaire | Où va le binaire |
|---|---|---|---|---|
go run . | oui | oui | non | répertoire temporaire, supprimé ensuite |
go build | oui | non | oui | répertoire courant (ou -o path) |
go install | oui | non | oui | $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 lancez | Nom du binaire |
|---|---|
go build dans le module example.com/hello | hello |
go build ./cmd/server | server |
go build main.go | main (d'après le premier fichier) |
go build -o bin/app . | bin/app |
n'importe lequel des cas ci-dessus avec GOOS=windows | mê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
| Flag | Ce qu'il fait |
|---|---|
-o name | fichier ou répertoire de sortie |
-v | affiche le nom des packages au fur et à mesure de la compilation |
-race | compile avec le détecteur de data races (plus lent, binaire plus gros ; pour les tests) |
-trimpath | retire 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 name | inclut 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 :
| GOOS | GOARCH | Cible |
|---|---|---|
linux | amd64 | la plupart des serveurs et conteneurs |
linux | arm64 | AWS Graviton, Raspberry Pi avec un OS 64 bits |
darwin | arm64 | Mac Apple Silicon |
darwin | amd64 | Mac Intel |
windows | amd64 | Windows 64 bits |
js | wasm | WebAssembly 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
| Commande | Rôle |
|---|---|
go test ./... | lancer les tests |
go mod tidy | ajouter les dépendances manquantes et retirer celles qui sont inutilisées |
go get pkg@version | ajouter ou changer une dépendance |
go clean -cache | vider le cache de build |
go env | afficher la configuration de Go |
go doc fmt.Println | afficher la documentation dans le terminal |
go list -m all | lister 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 ..