go run compila ed esegue un programma in un solo passaggio e non conserva il binario. go build compila e lascia un eseguibile nella directory corrente. go install compila e mette l'eseguibile in $HOME/go/bin. Tutti e tre compilano in codice macchina nativo; nessuno di loro interpreta nulla.
| Comando | Compila | Esegue | Conserva un binario | Dove finisce il binario |
|---|---|---|---|---|
go run . | sì | sì | no | directory temporanea, eliminata dopo |
go build | sì | no | sì | directory corrente (o -o path) |
go install | sì | no | sì | $GOBIN, altrimenti $GOPATH/bin |
Il programma qui sotto è quello usato negli esempi di questa pagina. L'editor lo esegue come farebbe go run.
go run
go run riceve un package (di solito ., la directory corrente) o una lista di file .go:
go run .
go run main.go
go run ./cmd/server
Tutto ciò che segue il package viene passato al tuo programma come argomenti:
go run . --port 8080 verbose
version: dev
built for: linux/amd64
args: [--port 8080 verbose]
Preferisci go run . a go run main.go. Indicare un file compila solo quel file, quindi appena il package ha un secondo file, le funzioni definite lì vengono segnalate come undefined. La pagina su package e import tratta quell'errore in dettaglio.
go run esegue anche un programma remoto a una versione specifica senza installarlo, il che è comodo per i generatori di codice:
go run golang.org/x/tools/cmd/stringer@v0.30.0 -type=Color
go build
go build compila il package nella directory corrente. Per un package main scrive un eseguibile; per un package di libreria compila, segnala gli errori e scarta il risultato.
go mod init example.com/hello
go build
ls
go.mod hello main.go
Il nome del binario segue queste regole:
| Esegui | Nome del binario |
|---|---|
go build nel modulo example.com/hello | hello |
go build ./cmd/server | server |
go build main.go | main (dal nome del primo file) |
go build -o bin/app . | bin/app |
uno qualsiasi dei precedenti con GOOS=windows | lo stesso nome più .exe |
Altre due forme che userai di continuo:
go build ./... # compile every package in the module
go vet ./... # static checks, covered below
./... significa "questa directory e tutte le directory sottostanti". go build ./... con più package main non scrive nessun binario; è un rapido controllo per verificare che tutto compili.
Flag di build utili
| Flag | Cosa fa |
|---|---|
-o name | file o directory di output |
-v | stampa i nomi dei package mentre vengono compilati |
-race | compila con il rilevatore di data race (binario più lento e più grande; per i test) |
-trimpath | rimuove dal binario i percorsi del file system locale, per build riproducibili |
-ldflags "-s -w" | elimina la tabella dei simboli e le informazioni di debug DWARF, rendendo il binario più piccolo |
-ldflags "-X main.version=1.4.0" | imposta una variabile stringa in fase di link |
-tags name | include i file protetti da un vincolo //go:build name |
Il flag -X è il modo in cui la maggior parte dei progetti Go imprime una versione nel binario. Funziona solo sulle variabili string a livello di package (non sulle costanti):
go build -o app -ldflags "-X main.version=1.4.0" .
./app
version: 1.4.0
built for: linux/amd64
args: []
Il binario registra anche le versioni dei suoi moduli e, da Go 1.18, il commit VCS da cui è stato compilato. go version -m ./app li stampa, e un programma può leggerli con runtime/debug.ReadBuildInfo.
go install
go install compila esattamente come go build e poi sposta l'eseguibile in $GOBIN, o in $GOPATH/bin quando GOBIN non è impostata (per impostazione predefinita $HOME/go/bin):
go install .
go env GOPATH
L'uso più comune è installare strumenti scritti in Go. Con @version installa un programma senza toccare il tuo go.mod:
go install golang.org/x/tools/gopls@latest
go install honnef.co/go/tools/cmd/staticcheck@latest
Se dopo la shell non trova uno strumento, $HOME/go/bin non è nel tuo PATH. Aggiungi export PATH=$PATH:$(go env GOPATH)/bin al profilo della tua shell.
Cross-compilazione con GOOS e GOARCH
Go può compilare per un altro sistema operativo o un'altra CPU da qualsiasi macchina, senza toolchain aggiuntive. Imposta due variabili d'ambiente per il comando di 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 .
In PowerShell, le variabili d'ambiente si impostano in modo diverso:
$env:GOOS = "linux"; $env:GOARCH = "amd64"; go build -o app-linux .
Le coppie più comuni:
| GOOS | GOARCH | Destinazione |
|---|---|---|
linux | amd64 | la maggior parte dei server e dei container |
linux | arm64 | AWS Graviton, Raspberry Pi con un sistema operativo a 64 bit |
darwin | arm64 | Mac con Apple Silicon |
darwin | amd64 | Mac Intel |
windows | amd64 | Windows a 64 bit |
js | wasm | WebAssembly in un browser |
go tool dist list stampa ogni coppia supportata (48 in Go 1.24).
La cross-compilazione è così semplice solo per il codice Go puro. Un package che usa cgo (codice C, per esempio alcuni driver SQLite) ha bisogno di un cross-compilatore C per la destinazione. Durante la cross-compilazione cgo è disattivato per impostazione predefinita, e impostare esplicitamente CGO_ENABLED=0 ti dà anche un binario Linux completamente statico, che è ciò che vuoi in un'immagine di container minimale scratch o distroless.
go fmt e go vet
Due controlli dovrebbero far parte di ogni flusso di lavoro, e della CI.
go fmt riscrive i file nell'unico stile ufficiale: tabulazioni, campi allineati, spaziatura normalizzata. È un wrapper di gofmt -l -w:
go fmt ./...
gofmt -l . # list files that are not formatted; empty output means clean
go vet segnala il codice che compila ma è quasi certamente sbagliato. Le incongruenze nei formati di Printf sono il caso classico:
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
Il programma compila e stampa %!s(int=3) items, che è esattamente il tipo di bug che vet esiste per intercettare. Altri controlli di vet riguardano la copia per valore di un sync.Mutex, il codice irraggiungibile, i tag delle struct con sintassi errata e un context.CancelFunc che non viene mai chiamato. go test esegue automaticamente una parte di questi controlli; go build non ne esegue nessuno.
Altri sottocomandi di go
| Comando | Scopo |
|---|---|
go test ./... | esegue i test |
go mod tidy | aggiunge le dipendenze mancanti e rimuove quelle inutilizzate |
go get pkg@version | aggiunge o modifica una dipendenza |
go clean -cache | svuota la cache di build |
go env | stampa la configurazione di Go |
go doc fmt.Println | mostra la documentazione nel terminale |
go list -m all | elenca ogni modulo della build |
Perché la seconda build è veloce
Go mette in cache i package compilati nella cache di build (go env GOCACHE). Una nuova build ricompila solo i package il cui sorgente o le cui dipendenze sono cambiati, quindi go run . su un progetto invariato parte quasi all'istante. Se una build si comporta in modo strano dopo aver cambiato versione di Go o variabili d'ambiente, go clean -cache la svuota; dovrebbe servirti di rado.
Domande frequenti
Qual è la differenza tra go run e go build?
go run compila il programma in una directory temporanea, lo esegue e butta via il binario. go build compila il programma e scrive il binario nella directory corrente, così puoi eseguirlo di nuovo o copiarlo altrove. Usa go run durante lo sviluppo e go build quando ti serve l'eseguibile.
Come imposto il nome del file di output di go build?
Usa -o: go build -o myapp . scrive myapp (su Windows, scrivi tu -o myapp.exe). Senza -o, go build chiama il binario come l'ultimo elemento del percorso di import del package, o come il primo file quando passi dei file .go, e aggiunge .exe quando compili per Windows.
Come faccio la cross-compilazione di Go per Linux o Windows?
Imposta GOOS e GOARCH per la build: GOOS=linux GOARCH=amd64 go build -o app-linux . oppure GOOS=windows GOARCH=amd64 go build . (che produce un .exe). Per il codice Go puro non serve nessuna toolchain aggiuntiva. go tool dist list stampa ogni coppia supportata.
Dove mette il binario go install?
In $GOBIN se è impostata, altrimenti in $GOPATH/bin, che per impostazione predefinita è $HOME/go/bin. Aggiungi quella directory al tuo PATH per eseguire gli strumenti installati per nome. go install example.com/tool@latest installa uno strumento senza aggiungerlo al tuo modulo.
go build esegue go vet?
No. go build si limita a compilare. go test esegue automaticamente una parte dei controlli di go vet, ma per l'insieme completo esegui tu go vet ./..., di solito in CI accanto a gofmt -l ..