Go Toolchain na prática: go run, go build, go test, go fmt e go vet

Capítulo 2

Tempo estimado de leitura: 8 minutos

+ Exercício

Visão geral da toolchain do Go no dia a dia

A toolchain do Go é um conjunto de comandos oficiais (executados via go) que cobre o ciclo completo de desenvolvimento: executar código (go run), compilar binários (go build), testar (go test), formatar (gofmt / go fmt) e analisar problemas comuns (go vet). A ideia é padronizar o fluxo: você escreve código, formata, valida com vet, roda testes e gera o binário final.

Como o Go encontra pacotes (módulos, import e diretórios)

No Go moderno, o ponto de partida é o arquivo go.mod, que define o módulo (ex.: module example.com/cli). A partir dele, o Go resolve imports usando:

  • Pacotes do módulo atual: imports que começam com o caminho do módulo (ex.: example.com/cli/internal/app) são encontrados dentro do diretório do projeto.
  • Dependências: imports externos são baixados e versionados automaticamente (quando necessário) e ficam disponíveis para build/test.
  • Biblioteca padrão: imports como fmt, os, net/http são resolvidos localmente.

O comando go env ajuda a inspecionar variáveis relevantes. Duas úteis no cotidiano:

  • go env GOMOD: mostra qual go.mod está sendo usado (ou vazio se você estiver fora de um módulo).
  • go env GOPATH: ainda é usado como local padrão de cache e downloads, mesmo em projetos com módulos.

Pacote vs. arquivo: por que isso importa

Quase sempre você trabalha com pacotes (diretórios). Um pacote é um conjunto de arquivos .go no mesmo diretório com o mesmo package. Muitos comandos aceitam:

  • Caminhos de pacote (ex.: ./..., ./cmd/mytool)
  • Arquivos (mais comum em exemplos rápidos, especialmente com go run)

Cache de build: o que é e quando é invalidado

O Go usa cache agressivo para acelerar builds e testes. Em geral, se nada relevante mudou, recompilar é quase instantâneo. O cache é invalidado quando:

Continue em nosso aplicativo e ...
  • Ouça o áudio com a tela desligada
  • Ganhe Certificado após a conclusão
  • + de 5000 cursos para você explorar!
ou continue lendo abaixo...
Download App

Baixar o aplicativo

  • Você altera arquivos .go do pacote ou de dependências.
  • Você altera arquivos que afetam o build (ex.: go.mod, go.sum).
  • Você muda flags que impactam o resultado (ex.: -race, tags de build, GOOS/GOARCH).
  • Você muda variáveis de ambiente que afetam compilação/links.

Comandos úteis para lidar com cache:

  • go clean -cache: limpa o cache de build.
  • go clean -testcache: limpa cache de testes (útil quando você quer forçar reexecução).
  • go env GOCACHE: mostra onde o cache fica.

go run na prática (executar rapidamente)

go run compila e executa um programa, normalmente sem deixar o binário final no diretório do projeto. É ideal para desenvolvimento rápido e para rodar ferramentas internas.

Executando um pacote

go run ./cmd/mytool

Esse formato é o mais comum em projetos com estrutura cmd/. O Go compila o pacote main daquele diretório e executa.

Executando com argumentos

Para passar argumentos ao seu programa, coloque -- antes dos argumentos (boa prática para evitar conflito com flags do próprio go):

go run ./cmd/mytool -- -name Ana -n 3

Executando arquivos diretamente

go run main.go

Útil em exemplos pequenos. Em projetos reais, prefira executar o pacote (diretório) para evitar confusão com múltiplos arquivos e dependências internas.

Flags úteis com go run

  • -v: mostra quais pacotes estão sendo compilados.
  • -race: habilita o detector de race conditions (apenas em plataformas suportadas; aumenta tempo e consumo).
go run -v -race ./cmd/mytool -- -name Ana -n 3

go build na prática (compilar binários)

go build compila pacotes. Para programas (package main), ele gera um executável. Para bibliotecas, ele apenas verifica e compila para o cache.

Build do pacote main

go build ./cmd/mytool

Por padrão, o binário é gerado no diretório atual com o nome do diretório do pacote (ex.: mytool).

Definindo nome e pasta de saída

go build -o bin/mytool ./cmd/mytool

Esse padrão (bin/) é comum para separar artefatos de build do código-fonte.

Build com informações detalhadas

  • -v: lista pacotes compilados.
  • -x: mostra os comandos internos executados (útil para depurar).
go build -v -x -o bin/mytool ./cmd/mytool

Build com race detector

go build -race -o bin/mytool ./cmd/mytool

Use para builds de desenvolvimento quando você suspeita de problemas de concorrência. Em geral, não é usado para release por custo e restrições.

Entendendo erros comuns de build

MensagemO que significaComo agir
package ... is not in stdImport foi interpretado como biblioteca padrão ou não foi resolvido no móduloVerifique o caminho do import, se está dentro do módulo, e se go.mod está correto
cannot find module providing package ...Dependência não encontradaRode go get (quando apropriado) ou go mod tidy para ajustar dependências
found packages X and Y in ...Arquivos no mesmo diretório com package diferenteSepare em diretórios distintos ou unifique o nome do pacote

Mini-projeto CLI para praticar go run e go build

Você vai criar um pequeno utilitário de linha de comando que gera saudações e, opcionalmente, faz trabalho concorrente para demonstrar -race em testes.

Estrutura sugerida

mytool/  go.mod  cmd/    mytool/      main.go  internal/    greet/      greet.go      counter.go      counter_test.go

Passo 1: criar o módulo

mkdir mytool && cd mytool go mod init example.com/mytool

Passo 2: implementar o pacote internal/greet

internal/greet/greet.go

package greet import "fmt" func Message(name string, times int) string { if times <= 0 { times = 1 } return fmt.Sprintf("Olá, %s! (x%d)", name, times) }

internal/greet/counter.go (intencionalmente simples para testes)

package greet type Counter struct { n int } func (c *Counter) Inc() { c.n++ } func (c *Counter) Value() int { return c.n }

Passo 3: criar o comando em cmd/mytool

cmd/mytool/main.go

package main import ( "flag" "fmt" "os" "example.com/mytool/internal/greet" ) func main() { name := flag.String("name", "mundo", "nome para saudar") times := flag.Int("n", 1, "quantidade") flag.Parse() msg := greet.Message(*name, *times) fmt.Fprintln(os.Stdout, msg) }

Passo 4: executar com go run

go run ./cmd/mytool -- -name Ana -n 3

Passo 5: compilar com go build

go build -o bin/mytool ./cmd/mytool ./bin/mytool -name Ana -n 3

Se você alterar apenas um arquivo pequeno, o próximo go build tende a ser bem mais rápido por causa do cache.

go test: testes, flags úteis e cache de testes

go test compila e executa testes. Ele procura arquivos *_test.go e funções TestXxx. Também pode executar benchmarks e exemplos.

Criando um teste simples

internal/greet/counter_test.go

package greet import ( "sync" "testing" ) func TestCounterSequential(t *testing.T) { var c Counter c.Inc() c.Inc() if c.Value() != 2 { t.Fatalf("expected 2, got %d", c.Value()) } } func TestCounterConcurrent(t *testing.T) { var c Counter var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) go func() { defer wg.Done() c.Inc() }() } wg.Wait() if c.Value() != 100 { t.Fatalf("expected 100, got %d", c.Value()) } }

Esse teste concorrente pode falhar de forma intermitente e, mesmo quando passa, pode esconder uma race condition. É exatamente o tipo de problema que o -race ajuda a detectar.

Rodando testes por pacote e por árvore

go test ./... go test ./internal/greet

Flags úteis do go test

  • -v: mostra o nome dos testes executados.
  • -run: filtra quais testes rodar (regex).
  • -count=1: desativa o cache de testes para essa execução.
  • -race: habilita detector de race conditions.
go test -v ./internal/greet go test -run TestCounterConcurrent -count=1 ./internal/greet go test -race ./internal/greet

Entendendo o cache de testes

O go test pode reutilizar resultados anteriores quando detecta que nada relevante mudou. Você verá algo como (cached) no output. Para forçar reexecução:

go test -count=1 ./... go clean -testcache

Padrões de qualidade: gofmt, go vet e um fluxo recomendado

gofmt (formatação padrão)

gofmt é o formatador oficial. Ele aplica um estilo consistente (indentação, alinhamento, espaçamento) e é o padrão aceito pela comunidade e ferramentas. Você pode usar:

  • gofmt diretamente (mais controle)
  • go fmt (atalho que formata pacotes)

Formatando um arquivo:

gofmt -w cmd/mytool/main.go

Formatando o projeto todo (recursivo):

gofmt -w .

Verificando se há arquivos não formatados (sem modificar):

gofmt -l .

Alternativa via toolchain:

go fmt ./...

go vet (análise estática para bugs comuns)

go vet procura padrões suspeitos que compilam, mas costumam indicar bug: formatação incorreta de Printf, uso indevido de append, cópias de locks, erros em tags, entre outros. Ele não substitui testes, mas pega problemas cedo.

Rodando no projeto:

go vet ./...

Se o vet apontar algo, trate como alerta sério. Exemplo clássico: usar fmt.Printf("%d", "texto") (tipo incompatível) pode passar despercebido em revisão, mas o vet acusa.

Fluxo prático de qualidade (rotina diária)

Um fluxo simples e efetivo para antes de commit/PR:

  • 1) Formatar: gofmt -w . (ou go fmt ./...)
  • 2) Analisar: go vet ./...
  • 3) Testar: go test ./...
  • 4) Se houver concorrência: go test -race ./... (quando aplicável)

Para depurar builds e entender o que está acontecendo, use -v (visibilidade) e -x (comandos internos). Para problemas intermitentes em testes, combine -count=1 com -race.

Agora responda o exercício sobre o conteúdo:

Ao executar um programa com go run e precisar passar argumentos para o seu binário (sem confundir com flags do comando go), qual é a forma recomendada?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

A boa prática é usar -- para separar as flags do comando go dos argumentos do programa, evitando conflitos e interpretações incorretas.

Próximo capitúlo

Módulos e pacotes em Go: go.mod, dependências e versionamento

Arrow Right Icon
Capa do Ebook gratuito Go (Golang) para Iniciantes: Fundamentos, Concorrência e Estrutura de Projetos
11%

Go (Golang) para Iniciantes: Fundamentos, Concorrência e Estrutura de Projetos

Novo curso

18 páginas

Baixe o app para ganhar Certificação grátis e ouvir os cursos em background, mesmo com a tela desligada.