- Na versão Go 1.26, foi introduzido o comando
go fix completamente reescrito, capaz de melhorar automaticamente o código usando os recursos mais recentes da linguagem e das bibliotecas
- A ferramenta detecta padrões de código por meio de dezenas de analisadores (analyzers) e aplica vários modernizadores (modernizers), como
minmax, rangeint e stringscut, para transformar código repetitivo ou ultrapassado em formas mais atuais
- Para dar suporte ao novo recurso
new(expr), foi adicionado o analisador newexpr, que pode simplificar automaticamente funções auxiliares como newInt
- O
go fix produz efeito de sinergia quando executado várias vezes, permitindo que analisadores diferentes proponham melhorias em sequência, além de incluir mesclagem automática em caso de conflito e remoção de imports desnecessários
- A equipe do Go planeja expandir a ferramenta no futuro com o paradigma de análise Self-service, para que desenvolvedores possam definir e distribuir modernizadores para suas próprias APIs
Visão geral do comando go fix
- No Go 1.26, o
go fix foi totalmente reimplementado, passando a oferecer conversão automática de codebases para o estilo mais moderno de Go
- O comando
go fix ./... modifica todos os pacotes abaixo do diretório atual
- A opção
-diff permite visualizar as mudanças antes
- A lista de analisadores registrados pode ser vista com
go tool fix help, incluindo várias regras de transformação como any, forvar, mapsloop e minmax
- Para executar apenas um analisador específico, use flags como
-any; para excluí-lo, defina -any=false
- Considerando diferenças de código por plataforma, é possível executar várias vezes para cada combinação de
GOOS e GOARCH
Modernizers — ferramentas de modernização de código
- Desde o Go 1.18, a introdução de genéricos ampliou bastante as possibilidades de simplificação de código
- Ex.: usar
maps.Keys para coletar chaves de map, strings.Cut para dividir strings
- Para resolver o problema de ferramentas de geração de código baseadas em LLM manterem padrões antigos, o texto destaca a necessidade de atualizar código open source para refletir os idiomas modernos de Go
- Os modernizadores incluídos no
go fix e no gopls aumentam a legibilidade do código e o efeito de aprendizado
- Exemplos de modernizadores:
- minmax: substitui instruções
if por funções min/max
- rangeint: converte laços
for de 3 cláusulas em range-over-int
- stringscut: simplifica código baseado em
strings.Index com strings.Cut
O recurso new(expr) no Go 1.26
- A função
new foi expandida para aceitar argumentos por valor, permitindo inicialização na forma new("go1.26")
- O analisador
newexpr encontra helpers como newInt, simplifica para return new(x) e substitui os pontos de chamada por new(expr)
- Só é aplicado quando a versão mínima do Go for atendida, como com a diretiva
go 1.26
- Pode ser aplicado em toda a codebase com o comando
$ go fix -newexpr ./...
- Depois do uso, funções auxiliares desnecessárias podem ser identificadas com a ferramenta
deadcode
Sinergia e tratamento de conflitos
- Existe um efeito de sinergia em que uma correção cria oportunidades para outras
- Ex.: após aplicar
minmax, podem surgir novas sugestões de transformação
- Também é possível haver otimizações em sequência, como
stringsbuilder → fmt.Fprintf
- O
go fix faz mesclagem automática de conflitos com um algoritmo de merge em 3 vias
- Em conflitos de sintaxe, a correção é ignorada e um aviso é exibido
- Conflitos semânticos, como remoção de variável ou import não utilizado, exigem ajuste manual
- Imports desnecessários são removidos automaticamente
Integração com o framework de análise do Go
go vet e go fix foram integrados para compartilhar um framework de análise comum
- O
vet é focado em detectar erros, enquanto o fix é focado em correções automáticas seguras
- Os analisadores podem ser executados em vários drivers, como
unitchecker, multichecker, gopls, staticcheck e Tricorder
- O sistema de facts permite compartilhar informações entre pacotes
- Ex.: inferir que
log.Printf é um wrapper de fmt.Printf
- O
gopls oferece diagnóstico em tempo real e sugestões de correção automática
Melhorias na infraestrutura de análise
- A expansão do pacote inspector melhora a eficiência da navegação em AST, com o tipo
Cursor oferecendo navegação para cima, baixo, esquerda e direita
- A indexação de chamadas de função com typeindex aumenta a velocidade de análise em até 1000 vezes
- Outras melhorias incluem:
- fornecimento do grafo de dependências da biblioteca padrão
- suporte a consulta da versão do Go por arquivo
- ampliação dos primitivos de refatoração para permitir modificações seguras, como comentar código
- Alguns modernizadores foram excluídos por mudanças sutis de comportamento (caso
append([]string{}, slice...) → slices.Clone(slice))
- Estão previstos para o futuro um motor de pattern matching, um test harness automatizado e uma biblioteca precisa de operadores de correção
Paradigma Self-service
- A partir do Go 1.26, foi anunciada a introdução do modelo de análise Self-service
- Desenvolvedores poderão definir e distribuir modernizadores para suas próprias APIs
- Será possível executá-los no nível do projeto, sem processo centralizado de aprovação
- Como primeiro passo, um recurso de annotation-driven inliner foi incluído em forma de prévia
- Planos futuros:
- execução de analisadores personalizados por carregamento dinâmico (dentro do
go fix ou do gopls)
- generalização de checks baseados em fluxo de controle, por exemplo, validar invariantes como “open seguido de close” e “lock seguido de unlock”
- O objetivo é melhorar a eficiência de manutenção e acelerar a adoção dos recursos mais recentes do Go
1 comentários
Comentários do Hacker News
No fim de 2024, quando assistentes de código com LLM se espalharam rapidamente, foi interessante notar que essas ferramentas tendiam a reproduzir estilos antigos de código Go presentes nos dados de treino
Mesmo ao pedir para usar sintaxe mais nova, às vezes ignoravam isso ou até negavam que ela existisse
Para que os modelos futuros reflitam os idiomas do Go 1.25 mais atuais, todo o código open source precisaria ser atualizado para esse estilo
magic_quotesMas, quando um LLM absorve dados errados, corrigir isso depois é quase impossível
É difícil rastrear em que base o modelo chegou a uma conclusão, então só resta torcer para que a próxima versão venha corrigida
Parece simples e passa em revisão, mas na prática faltam tratamento de erro e casos de borda
Se você coloca de volta no LLM depois da revisão, ele até produz algo que parece corrigido, mas acaba introduzindo data races ou deadlocks
É um problema recorrente em praticamente todos os modelos
Go tem ótima compatibilidade retroativa, então compila, mas o estilo do código fica muito diferente
Em Python, mudanças de API causam quebras reais de compatibilidade
Ainda assim, Go é excelente como linguagem para geração de código, graças à estabilidade da linguagem e da biblioteca padrão
Como alertou Rob Pike, essa tecnologia é uma poluição do ecossistema de software
Muita gente quer a slop da “conveniência”, mas esse é justamente o cerne do problema
Uma ferramenta que transforma automaticamente código-fonte para o estilo mais atual é realmente incrível
OpenRewrite, do Java, é um exemplo clássico, mas não lembro de algo muito parecido em outras linguagens
Quando isso vem embutido na linguagem, como em Go, o grau de maturidade da linguagem sobe muito
Imagino que novas linguagens vão se inspirar nessa abordagem integrada do Go
As IDEs da JetBrains conseguem refatorar milhões de linhas de código de uma vez ou converter automaticamente para sintaxe nova
Há recursos como ConvertToPrimaryConstructor
E o Structural Search and Replace atua no nível de sintaxe da linguagem, não só de texto simples
Os analisadores Roslyn do .NET também oferecem sugestões de correção de código na IDE
Link do tutorial
Isso deixou o código bem mais limpo
Ele troca
concatemapporconcatMap, por exemplo, ou simplifica expressõesifdesnecessáriasOs servidores LSP têm poucos recursos e nem refatorações básicas, como remover argumentos, costumam suportar
Estou pensando se uma combinação de jscodeshift com Claude daria conta disso
Graças a ferramentas de correção automática como o
go fix, Go é realmente uma linguagem excelenteEstou animado porque a nova funcionalidade
rangeinttambém deve ser aplicada automaticamente viago fixMeus parabéns ao time do Go
A velocidade de compilação também é inacreditavelmente alta
forloops com regex e corrigia à mão; agora essa ferramenta faz isso de um jeito muito mais eleganteNão foi mencionado no artigo, mas minha funcionalidade favorita é a diretiva
//go:fix inlineEla insere uma função de uma linha inline no chamador
Isso permite que autores de bibliotecas façam a migração automática de funções antigas para novas de forma natural
Mesmo quando o semver muda, dá para atualizar automaticamente com
go fixNum podcast do Wes McKinney que vi recentemente,
ele disse que Go é ideal para agentes de programação por causa do ciclo rápido de compilar e executar, do sistema de tipos forte e da segurança em multithreading
Isso me fez voltar a me interessar por Go
O conjunto consolidado de ferramentas e convenções do Go ajuda muito no desenvolvimento orientado por agentes
Com
go run main.go, já dá para subir o ambiente de desenvolvimento na hora, com suporte a múltiplas worktrees, configuração centralizada e até banco de dados migradoO housecat-inc/cheetah compartilha ferramentas assim
Estou pensando em adicionar
go fixa esse loop rápido que já incluigo generate,go build,go testego vetAo aprender Python, senti que existem formas demais e pouca consistência para fazer a mesma coisa
Cheguei até a sentir falta do C, onde geralmente há um único jeito
Fiquei curioso se Go já chegou nesse ponto
Queria saber se é uma linguagem em que dá para seguir boas práticas sem depender de ajuda de LLM
É impressionante o esforço para manter tudo simples e evitar complexidade
Recomendo para quem está cansado da confusão do Python
O conceito de self-service analyzer é realmente muito interessante
Parece algo que times de bibliotecas grandes ou de infraestrutura vão usar bastante
Isso faz pensar se até linguagens sem compatibilidade retroativa não poderiam ser viáveis com ferramentas assim
No ecossistema TypeScript, o biome cumpre esse papel
Por exemplo, ele recomenda
for...ofno lugar deforEach, e com ultracite o fluxo de trabalho fica bem mais suaveColoquei no arquivo
agents.mda instrução “execute biome fix depois das mudanças”, e isso ajuda a manter a qualidade do código automaticamenteÉ uma experiência muito mais leve e eficiente do que com eslint