Ferramentas: vet, fmt, lint
Esta aula apresenta as principais ferramentas de qualidade de código em Go: go vet para análise estática, gofmt para formatação, e golangci-lint como linter abrangente. Você aprenderá a usá-las individualmente e em conjunto, integrando-as ao seu fluxo de trabalho para garantir código limpo, consistente e livre de erros comuns.
Nesta aula, vamos explorar as ferramentas essenciais que todo desenvolvedor Go deve dominar para manter a qualidade do código: go vet, gofmt e golangci-lint. Essas ferramentas automatizam a detecção de problemas, padronizam a formatação e aplicam boas práticas, permitindo que você se concentre na lógica do programa em vez de se preocupar com detalhes mecânicos.
Embora o compilador go build já capture muitos erros, ele não detecta problemas sutis de lógica, suspeitas de código ou inconsistências de estilo. É aí que entram as ferramentas de análise estática e formatação. Ao incorporá-las ao seu fluxo de trabalho, você reduz drasticamente a ocorrência de bugs e melhora a legibilidade do código, facilitando a manutenção e a colaboração em equipe.
go vet
O comando go vet é uma ferramenta de análise estática embutida no ecossistema Go. Ela examina o código-fonte em busca de construções suspeitas que podem indicar bugs reais ou potenciais. Ao contrário do compilador, que verifica a sintaxe e os tipos, o go vet procura padrões problemáticos que geralmente escapam da compilação, como chamadas incorretas de fmt.Printf, uso indevido de copy, ou condições que são sempre verdadeiras ou falsas.
Para usar, basta executar go vet ./... no diretório do módulo. Ele percorrerá todos os pacotes e reportará quaisquer problemas encontrados. É uma prática recomendada rodar go vet antes de cada commit ou em um pipeline de CI/CD. A ferramenta é altamente personalizável: você pode habilitar ou desabilitar verificadores específicos com as flags -vet (para go test) ou usar variantes como go vet -vettool para ferramentas externas.
Exemplo de código que o go vet detectaria:
package main
import "fmt"
func main() {
// Erro: fmt.Printf espera um verbo de formatação, mas o argumento é uma string
fmt.Printf("Olá, %s", 42)
}
Ao rodar go vet, você verá uma mensagem como fmt.Printf format %s has arg 42 of wrong type int. Isso impede que você cometa erros de formatação que passariam despercebidos na compilação.
gofmt
O gofmt é o formatador oficial de código Go. Ele aplica um estilo consistente de indentação, espaçamento, alinhamento e quebras de linha, seguindo as convenções da comunidade. A grande vantagem é que ele elimina discussões sobre estilo: todo código Go, quando formatado com gofmt, fica idêntico em termos de estilo, o que facilita a leitura e a revisão por outros desenvolvedores.
Para formatar um arquivo, use gofmt -w arquivo.go para sobrescrever o arquivo com a versão formatada. Se preferir apenas visualizar a saída, use gofmt arquivo.go. Em projetos, é comum usar gofmt -l . para listar os arquivos que não estão formatados, permitindo identificar rapidamente o que precisa ser ajustado.
Exemplo de código não formatado:
package main
import "fmt"
func main(){
fmt.Println("Olá, mundo!")
}
Após executar gofmt -w main.go, o arquivo se torna:
package main
import "fmt"
func main() {
fmt.Println("Olá, mundo!")
}
Note a indentação com tabulação e o espaço entre main() e a chave. O gofmt também pode ser usado em conjunto com editores de texto, que geralmente o executam automaticamente ao salvar.
golangci-lint (visão geral)
O golangci-lint é uma ferramenta de linting agregada que reúne mais de 100 linters diferentes em um único binário. Ele combina a análise estática do go vet com linters de estilo, complexidade, segurança e desempenho, oferecendo uma solução completa para qualidade de código. É amplamente adotado em projetos open source e em empresas devido à sua flexibilidade e velocidade.
A instalação é simples: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest. Depois, você pode executar golangci-lint run no diretório do seu projeto. Ele analisará todos os arquivos e reportará problemas com a categoria do linter, como errcheck, govet, staticcheck, entre outros. Você pode configurar quais linters habilitar através de um arquivo .golangci.yml, ajustando o comportamento às necessidades do seu time.
Exemplo de configuração básica (.golangci.yml):
linters:
enable:
- errcheck
- govet
- staticcheck
- gosimple
- ineffassign
Com essa configuração, o golangci-lint verificará erros não tratados, problemas de vet, e código ineficiente. Ele também oferece uma opção de autocorreção com --fix, que aplica correções seguras automaticamente, como remover imports não utilizados.
Integração
Para aproveitar ao máximo essas ferramentas, é essencial integrá-las ao seu fluxo de trabalho diário. A maioria dos editores de código (VS Code, GoLand, Vim) possui suporte nativo ou plugins que executam gofmt e go vet automaticamente ao salvar. Isso garante que o código esteja sempre formatado e livre de problemas comuns antes mesmo de você executar os comandos manualmente.
Em ambientes de CI/CD, você pode adicionar etapas para rodar go vet e golangci-lint em cada pull request. Isso cria uma barreira de qualidade que impede a introdução de código problemático no repositório principal. Exemplo de pipeline em GitHub Actions:
name: CI
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.22'
- name: Run go vet
run: go vet ./...
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v3
Essa integração garante que todo código submetido seja verificado automaticamente, reduzindo a carga de revisão manual e melhorando a confiabilidade do projeto.
Boas práticas e observações finais
Além de usar essas ferramentas, é importante adotar uma cultura de qualidade no time. Defina um padrão de formatação e linting no início do projeto e documente as regras. Incentive todos a rodar os comandos localmente antes de enviar código. Lembre-se de que gofmt não é opcional: é o padrão oficial da linguagem, e desviar dele gera ruído desnecessário.
Para go vet, tenha em mente que ele não detecta todos os erros lógicos; é uma ferramenta complementar aos testes. Portanto, combine-o com testes unitários e de integração robustos. O golangci-lint, por sua vez, pode ser customizado para se adequar ao seu projeto, mas evite habilitar linters excessivamente restritivos que gerem muitos falsos positivos. Comece com o conjunto padrão e adicione linters conforme a necessidade.
Finalmente, mantenha suas ferramentas atualizadas. Novas versões do Go trazem melhorias no go vet e no gofmt, e o golangci-lint é atualizado frequentemente com novos linters e correções. Acompanhe os releases e ajuste sua configuração conforme o ecossistema evolui.
Referências
- Documentação oficial do go vet
- Documentação oficial do gofmt
- Site oficial do golangci-lint
- Repositório GitHub do golangci-lint
- Blog oficial da linguagem Go
- Effective Go
- Code Review Comments (Wiki do Go)
Exercícios
Explique a diferença entre
go vetego buildem termos de análise de código.✓ Resposta:go buildcompila o código e verifica erros de sintaxe e tipos, enquantogo vetrealiza uma análise estática mais profunda, procurando por padrões suspeitos que podem indicar bugs lógicos, como chamadas incorretas de funções ou condições tautológicas. Enquantogo buildgarante que o programa compile,go vetajuda a prevenir erros que não impedem a compilação, mas podem causar comportamento incorreto em tempo de execução.Qual é o comando para formatar todos os arquivos .go do diretório atual e subdiretórios?
✓ Resposta: O comando égofmt -w .(ougofmt -w ./...em módulos) para formatar todos os arquivos .go no diretório atual e subdiretórios, sobrescrevendo-os com a versão formatada.Como você habilitaria apenas os linters
goveteerrcheckno golangci-lint?✓ Resposta: Crie um arquivo.golangci.ymlcom o seguinte conteúdo:
Depois executelinters: enable: - govet - errcheckgolangci-lint run.Qual a importância de integrar essas ferramentas no CI/CD?
✓ Resposta: Integrargo vet,gofmtegolangci-lintno pipeline de CI/CD garante que todo código submetido seja automaticamente verificado quanto a problemas de estilo, erros comuns e más práticas. Isso promove consistência, detecta problemas cedo e reduz a carga de revisão manual, aumentando a qualidade geral do software.Escreva um pequeno trecho de código Go que contenha um erro que
go vetdetectaria e explique qual é o erro.✓ Resposta: Exemplo:
O erro é que o verbo de formataçãopackage main import "fmt" func main() { x := 10 fmt.Printf("%d", x) // correto fmt.Printf("%s", x) // erro: %s espera string, mas x é int }%sé usado para um inteiro, o quego vetsinaliza como uma chamada inválida defmt.Printf.