go run kompiluje i uruchamia program w jednym kroku i nie zostawia pliku wykonywalnego. go build kompiluje i zostawia plik wykonywalny w bieżącym katalogu. go install kompiluje i umieszcza plik wykonywalny w $HOME/go/bin. Wszystkie trzy kompilują do natywnego kodu maszynowego; żadna z nich niczego nie interpretuje.
| Komenda | Kompiluje | Uruchamia | Zostawia plik wykonywalny | Dokąd trafia plik wykonywalny |
|---|---|---|---|---|
go run . | tak | tak | nie | katalog tymczasowy, potem usuwany |
go build | tak | nie | tak | bieżący katalog (lub -o path) |
go install | tak | nie | tak | $GOBIN, w przeciwnym razie $GOPATH/bin |
Poniższy program jest używany w przykładach na tej stronie. Edytor uruchamia go tak, jak zrobiłoby to go run.
go run
go run przyjmuje pakiet (zwykle ., czyli bieżący katalog) albo listę plików .go:
go run .
go run main.go
go run ./cmd/server
Wszystko po pakiecie trafia do programu jako argumenty:
go run . --port 8080 verbose
version: dev
built for: linux/amd64
args: [--port 8080 verbose]
Wybieraj go run . zamiast go run main.go. Podanie nazwy pliku kompiluje tylko ten plik, więc gdy tylko pakiet ma drugi plik, zdefiniowane w nim funkcje są zgłaszane jako undefined. Strona o pakietach i importach szczegółowo omawia ten błąd.
go run potrafi też uruchomić zdalny program w konkretnej wersji bez instalowania go, co przydaje się przy generatorach kodu:
go run golang.org/x/tools/cmd/stringer@v0.30.0 -type=Color
go build
go build kompiluje pakiet z bieżącego katalogu. Dla pakietu main zapisuje plik wykonywalny; dla pakietu bibliotecznego kompiluje go, zgłasza błędy i odrzuca wynik.
go mod init example.com/hello
go build
ls
go.mod hello main.go
Nazwa pliku wykonywalnego wynika z tych reguł:
| Uruchamiasz | Nazwa pliku wykonywalnego |
|---|---|
go build w module example.com/hello | hello |
go build ./cmd/server | server |
go build main.go | main (od nazwy pierwszego pliku) |
go build -o bin/app . | bin/app |
dowolne z powyższych z GOOS=windows | ta sama nazwa plus .exe |
Dwie kolejne formy, których będziesz używać bez przerwy:
go build ./... # compile every package in the module
go vet ./... # static checks, covered below
./... oznacza "ten katalog i każdy katalog pod nim". go build ./... z kilkoma pakietami main nie zapisuje żadnych plików wykonywalnych; to szybkie sprawdzenie, czy wszystko się kompiluje.
Przydatne flagi budowania
| Flaga | Co robi |
|---|---|
-o name | plik lub katalog wyjściowy |
-v | wypisuje nazwy pakietów podczas kompilacji |
-race | buduje z detektorem wyścigów danych (wolniej, większy plik; do testów) |
-trimpath | usuwa lokalne ścieżki systemu plików z pliku wykonywalnego, dla powtarzalnych buildów |
-ldflags "-s -w" | usuwa tablicę symboli i informacje debugowania DWARF, co zmniejsza plik |
-ldflags "-X main.version=1.4.0" | ustawia zmienną typu string podczas linkowania |
-tags name | dołącza pliki chronione ograniczeniem //go:build name |
Flaga -X to sposób, w jaki większość projektów Go wpisuje wersję do pliku wykonywalnego. Działa tylko na zmiennych string na poziomie pakietu (nie na stałych):
go build -o app -ldflags "-X main.version=1.4.0" .
./app
version: 1.4.0
built for: linux/amd64
args: []
Plik wykonywalny zapisuje też wersje swoich modułów, a od Go 1.18 także commit VCS, z którego został zbudowany. go version -m ./app je wypisuje, a program może je odczytać przez runtime/debug.ReadBuildInfo.
go install
go install buduje dokładnie tak jak go build, a potem przenosi plik wykonywalny do $GOBIN albo do $GOPATH/bin, gdy GOBIN nie jest ustawione (domyślnie $HOME/go/bin):
go install .
go env GOPATH
Najczęściej służy do instalowania narzędzi napisanych w Go. Z @version instaluje program bez ruszania twojego go.mod:
go install golang.org/x/tools/gopls@latest
go install honnef.co/go/tools/cmd/staticcheck@latest
Jeśli potem powłoka nie może znaleźć narzędzia, $HOME/go/bin nie jest w twoim PATH. Dodaj export PATH=$PATH:$(go env GOPATH)/bin do profilu powłoki.
Kompilacja skrośna przez GOOS i GOARCH
Go potrafi budować dla innego systemu operacyjnego lub procesora z dowolnej maszyny, bez dodatkowego zestawu narzędzi. Ustaw dwie zmienne środowiskowe dla komendy budowania:
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 .
W PowerShellu zmienne środowiskowe ustawia się inaczej:
$env:GOOS = "linux"; $env:GOARCH = "amd64"; go build -o app-linux .
Najczęstsze pary:
| GOOS | GOARCH | Cel |
|---|---|---|
linux | amd64 | większość serwerów i kontenerów |
linux | arm64 | AWS Graviton, Raspberry Pi z 64-bitowym systemem |
darwin | arm64 | Maki z Apple Silicon |
darwin | amd64 | Maki z procesorem Intel |
windows | amd64 | 64-bitowy Windows |
js | wasm | WebAssembly w przeglądarce |
go tool dist list wypisuje każdą obsługiwaną parę (48 w Go 1.24).
Kompilacja skrośna jest tak prosta tylko dla czystego kodu Go. Pakiet używający cgo (kodu w C, na przykład niektóre sterowniki SQLite) potrzebuje kompilatora skrośnego C dla platformy docelowej. Przy kompilacji skrośnej cgo jest domyślnie wyłączone, a jawne ustawienie CGO_ENABLED=0 daje też w pełni statyczny plik wykonywalny dla Linuksa, czyli to, czego potrzebujesz w minimalnym obrazie kontenera scratch lub distroless.
go fmt i go vet
Dwa sprawdzenia powinny być w każdym procesie pracy i w CI.
go fmt przepisuje pliki w jednym oficjalnym stylu: tabulatory, wyrównane pola, ujednolicone odstępy. To nakładka na gofmt -l -w:
go fmt ./...
gofmt -l . # list files that are not formatted; empty output means clean
go vet zgłasza kod, który się kompiluje, ale prawie na pewno jest błędny. Klasycznym przykładem są niezgodności formatów Printf:
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
Program się kompiluje i wypisuje %!s(int=3) items, a to dokładnie ten rodzaj błędu, do którego wyłapywania istnieje vet. Inne sprawdzenia vet obejmują kopiowanie sync.Mutex przez wartość, nieosiągalny kod, tagi struktur ze złą składnią i context.CancelFunc, która nigdy nie zostaje wywołana. go test automatycznie uruchamia część tych sprawdzeń; go build nie uruchamia żadnego.
Inne podkomendy go
| Komenda | Cel |
|---|---|
go test ./... | uruchamia testy |
go mod tidy | dodaje brakujące i usuwa nieużywane zależności |
go get pkg@version | dodaje lub zmienia zależność |
go clean -cache | czyści cache budowania |
go env | wypisuje konfigurację Go |
go doc fmt.Println | pokazuje dokumentację w terminalu |
go list -m all | wymienia każdy moduł w buildzie |
Dlaczego drugi build jest szybki
Go przechowuje skompilowane pakiety w cache budowania (go env GOCACHE). Ponowny build kompiluje tylko pakiety, których kod źródłowy lub zależności się zmieniły, więc go run . w niezmienionym projekcie startuje niemal natychmiast. Jeśli po zmianie wersji Go lub zmiennych środowiskowych build zachowuje się dziwnie, go clean -cache czyści cache; rzadko powinno to być potrzebne.
Najczęściej zadawane pytania
Czym różni się go run od go build?
go run kompiluje program do katalogu tymczasowego, uruchamia go i wyrzuca plik wykonywalny. go build kompiluje program i zapisuje plik wykonywalny w bieżącym katalogu, żeby można go było uruchomić ponownie albo skopiować gdzie indziej. Używaj go run podczas pracy nad kodem, a go build, gdy potrzebujesz pliku wykonywalnego.
Jak ustawić nazwę pliku wynikowego go build?
Użyj -o: go build -o myapp . zapisuje myapp (w Windows samodzielnie dopisz rozszerzenie: -o myapp.exe). Bez -o go build nazywa plik wykonywalny od ostatniego elementu ścieżki importu pakietu albo od pierwszego pliku, gdy podajesz pliki .go, i dodaje .exe przy budowaniu dla Windows.
Jak skompilować Go dla Linuksa albo Windows z innego systemu?
Ustaw GOOS i GOARCH dla buildu: GOOS=linux GOARCH=amd64 go build -o app-linux . albo GOOS=windows GOARCH=amd64 go build . (co daje plik .exe). Dla czystego kodu Go nie potrzeba żadnego dodatkowego zestawu narzędzi. go tool dist list wypisuje każdą obsługiwaną parę.
Gdzie go install umieszcza plik wykonywalny?
W $GOBIN, jeśli jest ustawione, a w przeciwnym razie w $GOPATH/bin, czyli domyślnie w $HOME/go/bin. Dodaj ten katalog do PATH, żeby uruchamiać zainstalowane narzędzia po nazwie. go install example.com/tool@latest instaluje narzędzie bez dodawania go do twojego modułu.
Czy go build uruchamia go vet?
Nie. go build tylko kompiluje. go test automatycznie uruchamia część sprawdzeń go vet, ale pełny zestaw uruchamiasz przez go vet ./..., zwykle w CI obok gofmt -l ..