Pular para o conteúdo

Tool Dependencies

Go 1.24 (fevereiro de 2025) introduziu a diretiva tool no go.mod, que finalmente resolve um problema antigo: como gerenciar ferramentas de desenvolvimento (linters, geradores de código, etc.) de forma padronizada.

Desenvolvedores criavam um arquivo especial para rastrear ferramentas:

//go:build tools
// +build tools
package tools
import (
_ "github.com/golangci/golangci-lint/cmd/golangci-lint"
_ "golang.org/x/tools/cmd/goimports"
_ "github.com/swaggo/swag/cmd/swag"
)

Problemas com esta abordagem:

  • ❌ Confuso para novos desenvolvedores
  • ❌ Build tags obscuros
  • ❌ Ferramentas misturadas com dependências de runtime
  • ❌ Não havia padrão oficial
module github.com/usuario/projeto
go 1.27.0
// Ferramentas de desenvolvimento
tool (
golang.org/x/tools/cmd/goimports
github.com/golangci/golangci-lint/v2/cmd/golangci-lint
github.com/swaggo/swag/cmd/swag
)
Janela do terminal
# Adicionar uma ferramenta
go get -tool golang.org/x/tools/cmd/goimports@latest
# Adicionar múltiplas ferramentas
go get -tool \
github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest \
github.com/swaggo/swag/cmd/swag@latest \
golang.org/x/tools/cmd/stringer@latest
# Adicionar versão específica
go get -tool golang.org/x/tools/cmd/goimports@v0.38.0
Janela do terminal
# Executar ferramenta registrada
go tool goimports -w .
go tool golangci-lint run
go tool swag init
# Lista todas as ferramentas disponíveis
go tool

A diretiva tool registra o pacote executável. O comando go get -tool também adiciona o módulo da ferramenta em require, com sua versão, e atualiza go.sum. Os trechos abaixo mostram a organização das diretivas; use o comando para gerar os requisitos completos.

module github.com/empresa/api
go 1.27.0
// Dependências de runtime
require (
github.com/gin-gonic/gin v1.10.0
gorm.io/gorm v1.25.7
)
// Ferramentas de desenvolvimento
tool (
golang.org/x/tools/cmd/goimports
github.com/golangci/golangci-lint/v2/cmd/golangci-lint
github.com/swaggo/swag/cmd/swag
golang.org/x/tools/cmd/stringer
github.com/google/wire/cmd/wire
)
Janela do terminal
# 1. Clone o projeto
git clone https://github.com/empresa/api
cd api
# 2. Baixe dependências E ferramentas
go mod download
# 3. Instale ferramentas no GOBIN
go install tool
# 4. Pronto! Todas as ferramentas disponíveis
go tool goimports -w .
golangci-lint run # Também disponível no PATH
Janela do terminal
# Adicionar ferramenta
go get -tool <package>@<version>
# Atualizar todas as ferramentas
go get tool
# Atualizar ferramenta específica
go get -tool <package>@latest
# Remover ferramenta
go get -tool <package>@none
# Listar ferramentas
go list tool
Janela do terminal
# Via go tool (usa versão do go.mod)
go tool <nome> [args]
# Instalar no GOBIN
go install tool # Instala todas
go install <package> # Instala uma específica na versão selecionada pelo módulo
# Executar diretamente (se instalada)
goimports -w .
Aspecto tools.go (antigo) tool (Go 1.24+)
Clareza Obscuro Explícito e oficial
Requisitos de versão Compartilham o grafo do projeto Compartilham o grafo do projeto
Execução go run manual go tool integrado
Cache Depende do comando e da versão do Go Executável mantido no build cache
Padrão Hack não oficial Suporte oficial
tool (
github.com/golangci/golangci-lint/v2/cmd/golangci-lint
golang.org/x/tools/cmd/goimports
mvdan.cc/gofumpt
)
Janela do terminal
# Executar linting
go tool golangci-lint run
# Formatar código
go tool goimports -w .
go tool gofumpt -l -w .
tool (
github.com/google/wire/cmd/wire
golang.org/x/tools/cmd/stringer
github.com/swaggo/swag/cmd/swag
google.golang.org/protobuf/cmd/protoc-gen-go
)
Janela do terminal
# Gerar código
go tool wire ./...
go tool stringer -type=Status
go tool swag init
tool (
github.com/onsi/ginkgo/v2/ginkgo
github.com/golang/mock/mockgen
gotest.tools/gotestsum
)
Janela do terminal
# Executar testes
go tool gotestsum ./...
go tool ginkgo -r
# Gerar mocks
go tool mockgen -source=interface.go

Go 1.24+ mantém os executáveis das ferramentas no build cache. O comando continua executando a ferramenta a cada chamada; o que pode ser reaproveitado é a compilação.

Janela do terminal
go tool goimports -l .
go tool goimports -l .

O tempo depende da compilação e do trabalho realizado pela ferramenta. No Go 1.27, go tool também mostra os nomes curtos disponíveis para ferramentas declaradas no módulo. Um nome curto só pode ser usado quando identifica uma única ferramenta.

name: CI
on: [push]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.27.1'
# Ferramentas são baixadas automaticamente
- run: go mod download
# Executar linting
- run: go tool golangci-lint run
# Verificar formatação
- run: |
go tool goimports -l .
test -z "$(go tool goimports -l .)"
.PHONY: tools lint fmt test
# Instalar ferramentas
tools:
go install tool
# Linting
lint:
go tool golangci-lint run --timeout=5m
# Formatação
fmt:
go tool goimports -w .
go tool gofumpt -l -w .
# Gerar código
generate:
go tool wire ./...
go tool stringer -type=Status
# Executar tudo
all: tools fmt generate lint test

Ferramentas participam do mesmo grafo de dependências do projeto. Um requisito maior pode mudar a versão usada pelos dois:

Seu projeto: require github.com/pkg/errors v0.9.1
Ferramenta: require github.com/pkg/errors v0.8.0
Versão selecionada pelo MVS: v0.9.1
Janela do terminal
# MVS escolhe o maior requisito entre os módulos envolvidos
# Geralmente funciona bem
go mod tidy
Janela do terminal
# Criar um módulo separado para ferramentas
mkdir tools
cd tools
GOWORK=off go mod init example.com/projeto/tools
GOWORK=off go get -tool golang.org/x/tools/cmd/goimports@v0.38.0
cd ..
# Usar seu arquivo de requisitos a partir da raiz do projeto
GOWORK=off go tool -modfile=tools/go.mod goimports -l .
//go:build tools
package tools
import (
_ "golang.org/x/tools/cmd/goimports"
_ "github.com/golangci/golangci-lint/v2/cmd/golangci-lint"
)
go.mod
tool (
golang.org/x/tools/cmd/goimports
github.com/golangci/golangci-lint/v2/cmd/golangci-lint
)
Janela do terminal
# 1. Remover tools.go
rm tools.go
# 2. Adicionar ferramentas via go get -tool
go get -tool golang.org/x/tools/cmd/goimports@latest
go get -tool github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
# 3. Limpar go.mod
go mod tidy
# 4. Testar
go tool goimports --help
go tool golangci-lint --version
# 5. Commit
git add go.mod go.sum
git rm tools.go
git commit -m "Migrate to tool directive (Go 1.24)"
  • Use tool directive para todas as ferramentas de desenvolvimento
  • Documente ferramentas necessárias no README
  • Versione ferramentas (não use @latest em produção)
  • Inclua go install tool no setup de novos desenvolvedores
  • Use cache de ferramentas no CI para velocidade
  • Misturar ferramentas com dependências de runtime manualmente
  • Manter tools.go em projetos Go 1.24+
  • Usar go run para ferramentas (use go tool)
  • Ignorar conflitos de dependências sem investigar
Janela do terminal
# Ferramenta não encontrada
$ go tool goimports
go: unknown tool goimports
# Solução: Adicionar ao go.mod
go get -tool golang.org/x/tools/cmd/goimports@latest
Janela do terminal
# Resolver conflito
go get -tool <package>@<versão-compatível>
go mod tidy
# Ou usar go.mod separado
Janela do terminal
# Limpar e reconstruir cache
go clean -cache
go tool <ferramenta> # Reconstrói cache

A diretiva tool do Go 1.24 é uma adição extremamente bem-vinda:

  • 🎯 Padroniza gerenciamento de ferramentas
  • 🚀 Simplifica setup de novos desenvolvedores
  • ⚡ Melhora performance com caching
  • 📦 Organiza dependências claramente