Menu

go run, go build e go install: compilar e executar Go

O que go run, go build e go install fazem, como o Go dá nome ao binário, como fazer compilação cruzada com GOOS e GOARCH e as verificações go fmt e go vet para rodar antes do commit.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

go run compila e executa um programa em um passo só e não guarda binário. go build compila e deixa um executável no diretório atual. go install compila e coloca o executável em $HOME/go/bin. Os três compilam para código de máquina nativo; nenhum deles interpreta nada.

ComandoCompilaExecutaGuarda um binárioPara onde vai o binário
go run .simsimnãodiretório temporário, apagado depois
go buildsimnãosimdiretório atual (ou -o caminho)
go installsimnãosim$GOBIN, senão $GOPATH/bin

O programa abaixo é o usado nos exemplos desta página. O editor o executa como o go run faria.

go run

go run recebe um pacote (normalmente ., o diretório atual) ou uma lista de arquivos .go:

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

Tudo o que vem depois do pacote é repassado ao seu programa como argumentos:

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

Prefira go run . a go run main.go. Apontar um arquivo compila só esse arquivo, então assim que o pacote ganha um segundo arquivo, as funções definidas nele aparecem como undefined. A página de pacotes e imports explica esse erro em detalhes.

O go run também executa um programa remoto em uma versão específica sem instalá-lo, o que é útil para geradores de código:

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

go build

go build compila o pacote do diretório atual. Para um pacote main ele grava um executável; para um pacote de biblioteca ele compila, reporta os erros e descarta o resultado.

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

O nome do binário segue estas regras:

Você executaNome do binário
go build no módulo example.com/hellohello
go build ./cmd/serverserver
go build main.gomain (nome do primeiro arquivo)
go build -o bin/app .bin/app
qualquer um dos anteriores com GOOS=windowso mesmo nome mais .exe

Mais duas formas que você vai usar o tempo todo:

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

./... significa "este diretório e todos os diretórios abaixo dele". go build ./... com vários pacotes main não grava binário nenhum; é uma verificação rápida de "tudo compila?".

Flags de build úteis

FlagO que faz
-o nomearquivo ou diretório de saída
-vimprime o nome dos pacotes conforme compilam
-racecompila com o detector de data race (mais lento, binário maior; para testes)
-trimpathremove caminhos do sistema de arquivos local do binário, para builds reproduzíveis
-ldflags "-s -w"remove a tabela de símbolos e as informações de depuração DWARF, deixando o binário menor
-ldflags "-X main.version=1.4.0"define uma variável string na hora do link
-tags nomeinclui arquivos protegidos por uma restrição //go:build nome

A flag -X é como a maioria dos projetos Go grava a versão no binário. Ela só funciona com variáveis string de nível de pacote (não com constantes):

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

O binário também registra as versões dos módulos e, desde o Go 1.18, o commit do controle de versão a partir do qual foi compilado. go version -m ./app imprime essas informações, e um programa pode lê-las com runtime/debug.ReadBuildInfo.

go install

go install compila exatamente como o go build e depois move o executável para $GOBIN, ou para $GOPATH/bin quando GOBIN não está definido (por padrão $HOME/go/bin):

go install .
go env GOPATH

O uso mais comum é instalar ferramentas escritas em Go. Com @versão ele instala um programa sem mexer no seu go.mod:

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

Se depois disso o shell não encontrar a ferramenta, $HOME/go/bin não está no seu PATH. Adicione export PATH=$PATH:$(go env GOPATH)/bin ao perfil do seu shell.

Compilação cruzada com GOOS e GOARCH

Go compila para outro sistema operacional ou outra CPU a partir de qualquer máquina, sem toolchain extra. Defina duas variáveis de ambiente para o comando 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 .

No PowerShell, as variáveis de ambiente são definidas de outro jeito:

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

Os pares mais comuns:

GOOSGOARCHAlvo
linuxamd64a maioria dos servidores e containers
linuxarm64AWS Graviton, Raspberry Pi com sistema de 64 bits
darwinarm64Macs com Apple Silicon
darwinamd64Macs Intel
windowsamd64Windows de 64 bits
jswasmWebAssembly no navegador

go tool dist list imprime todos os pares suportados (48 no Go 1.24).

A compilação cruzada só é fácil assim para código Go puro. Um pacote que usa cgo (código C, por exemplo alguns drivers de SQLite) precisa de um compilador C cruzado para o alvo. Na compilação cruzada o cgo vem desabilitado por padrão, e definir CGO_ENABLED=0 explicitamente também gera um binário Linux totalmente estático, que é o que você quer em uma imagem de container mínima, scratch ou distroless.

go fmt e go vet

Duas verificações devem estar em todo fluxo de trabalho, e no CI.

go fmt reescreve os arquivos no único estilo oficial: tabs, campos alinhados, espaçamento normalizado. É um atalho para gofmt -l -w:

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

go vet aponta código que compila mas quase certamente está errado. Formatos de Printf que não batem com os argumentos são o caso clássico:

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

O programa compila e imprime %!s(int=3) items, que é justamente o tipo de bug que o vet existe para pegar. Outras verificações do vet incluem copiar um sync.Mutex por valor, código inalcançável, struct tags com sintaxe errada e uma context.CancelFunc que nunca é chamada. go test roda um subconjunto dessas verificações automaticamente; go build não roda nenhuma.

Outros subcomandos do go

ComandoPara que serve
go test ./...roda os testes
go mod tidyadiciona as dependências que faltam e remove as que não são usadas
go get pkg@versionadiciona ou muda uma dependência
go clean -cacheesvazia o cache de build
go envimprime a configuração do Go
go doc fmt.Printlnmostra a documentação no terminal
go list -m alllista todos os módulos do build

Por que o segundo build é rápido

O Go guarda os pacotes compilados no cache de build (go env GOCACHE). Um novo build recompila só os pacotes cujo código ou cujas dependências mudaram, então go run . em um projeto sem alterações começa quase na hora. Se um build se comportar de forma estranha depois de trocar a versão do Go ou variáveis de ambiente, go clean -cache limpa o cache; você raramente vai precisar disso.

Perguntas frequentes

Qual a diferença entre go run e go build?

go run compila o programa em um diretório temporário, executa e descarta o binário. go build compila o programa e grava o binário no diretório atual, para você executar de novo ou copiar para outro lugar. Use go run durante o desenvolvimento e go build quando precisar do executável.

Como definir o nome do arquivo gerado pelo go build?

Use -o: go build -o myapp . grava myapp (no Windows, escreva você mesmo -o myapp.exe). Sem -o, o go build dá ao binário o nome do último elemento do caminho de import do pacote, ou do primeiro arquivo quando você passa arquivos .go, e acrescenta .exe ao compilar para Windows.

Como fazer compilação cruzada de Go para Linux ou Windows?

Defina GOOS e GOARCH para o build: GOOS=linux GOARCH=amd64 go build -o app-linux . ou GOOS=windows GOARCH=amd64 go build . (que gera um .exe). Nenhuma toolchain extra é necessária para código Go puro. go tool dist list imprime todos os pares suportados.

Onde o go install coloca o binário?

Em $GOBIN se estiver definido; senão em $GOPATH/bin, que por padrão é $HOME/go/bin. Adicione esse diretório ao seu PATH para executar as ferramentas instaladas pelo nome. go install example.com/tool@latest instala uma ferramenta sem adicioná-la ao seu módulo.

O go build executa o go vet?

Não. go build só compila. go test roda automaticamente um subconjunto das verificações do go vet, mas para o conjunto completo rode você mesmo go vet ./..., normalmente no CI ao lado de gofmt -l ..

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR