O Go é a melhor linguagem para código escrito por IA porque um modelo consegue escrevê-lo de forma fiável e tu consegues verificar o que ele escreveu. A linguagem é pequena, por isso um modelo tem poucas formas de escrever a mesma coisa. Todos os ficheiros Go são formatados da mesma maneira, por isso o output parece-se com o código com que o modelo aprendeu. O compilador rejeita imports e variáveis não usados. A promessa de compatibilidade do Go 1 garante que as APIs que um modelo aprendeu há anos continuam a funcionar hoje. E a biblioteca padrão cobre a maior parte de um backend, por isso o modelo raramente precisa de um pacote que possa errar. Quando é um agente que escreve a maior parte do diff, são estas propriedades que decidem quanto do teu tempo vai para a revisão.
Resumo rápido
- O código de IA costuma falhar por estar quase certo. 66 % dos programadores dizem que o que mais os frustra nas ferramentas de IA é código que está «quase certo, mas não totalmente» (Stack Overflow Developer Survey, 2025). A melhor linguagem para código escrito por IA é aquela onde esses quase acertos são mais fáceis de apanhar.
- O Go mantém o output dos modelos curto e previsível. A especificação tem 25 palavras-chave (Go spec), e os autores do Multi-SWE-bench concluíram que o Go «apresenta um consumo de tokens relativamente baixo, tanto no input como no output, provavelmente devido à sua sintaxe minimalista e às suas convenções claras» (Multi-SWE-bench, 2025).
- O compilador não tem avisos. O Go «recusa-se a compilar programas com variáveis ou imports não usados» e só reporta erros que impedem a compilação (Go FAQ). O relatório Octoverse do GitHub diz que «os sistemas tipados ajudam a identificar mais cedo no pipeline os erros de compilação gerados por LLMs» (GitHub Octoverse, 2025).
- O código Go de 2012 ainda compila. A promessa do Go 1 garante que os programas antigos continuam a compilar «sem alterações» (Go 1 compatibility), por isso os padrões nos dados de treino de um modelo continuam válidos.
- Os agentes trabalham melhor com uma verificação que conseguem correr. Nas orientações da Anthropic para o Claude Code: «Dá ao Claude algo que produza um passou ou falhou, e o ciclo fecha-se sozinho» (Claude Code docs, 2026). O Go traz essas verificações com a linguagem:
go build,go vetego test -race.
O que o código escrito por IA precisa de uma linguagem
Uma linguagem adequa-se a código escrito por IA quando se sai bem em quatro coisas:
- O modelo consegue escrevê-la com fiabilidade. Uma linguagem pequena com um estilo comum deixa menos formas de errar.
- As ferramentas conseguem verificá-la sem um humano. Tipos estáticos, erros de compilação rigorosos e um test runner incluído rejeitam output mau antes de alguém o ler.
- Uma pessoa consegue revê-la depressa. Código sem fluxo de controlo escondido e sem magia deixa quem revê perceber o que um diff faz só a partir do diff.
- O que o modelo aprendeu continua a ser verdade. Os dados de treino têm meses ou anos, por isso a linguagem e as suas bibliotecas têm de continuar a funcionar como funcionavam.
O Go foi desenhado na Google para bases de código grandes trabalhadas por equipas grandes, muito antes de existirem assistentes de programação. As mesmas escolhas que tornaram o Go fácil de aprender para quem chega a uma equipa tornam-no fácil de escrever para um modelo e fácil de rever para ti.
Uma linguagem pequena que os modelos acertam
O Go tem menos funcionalidades do que a maioria das linguagens usadas em produção, o que deixa a um modelo menos formas de escrever algo engenhoso e errado.
A especificação reserva 25 palavras-chave (Go spec). Não há classes nem herança, nem exceções, nem sobrecarga de operadores, nem macros, nem conversões numéricas implícitas. Os ciclos são for e mais nada. O comportamento vem de funções simples, structs e interfaces pequenas. Quando um modelo escreve um handler HTTP em Go, há só meia dúzia de formas razoáveis de o fazer, e todas se parecem. Palavras-chave do Go: as 25 palavras reservadas explicadas percorre a lista completa.
Uma linguagem pequena também significa menos texto por tarefa. Os autores do Multi-SWE-bench mediram o uso de tokens em várias linguagens e o Go ficou entre os mais baixos, tanto no input como no output (Multi-SWE-bench, 2025). Menos tokens por alteração tornam cada tarefa mais barata e deixam mais espaço na janela de contexto para o teu próprio código.
Todos os ficheiros Go têm o mesmo aspeto
O gofmt faz parte da toolchain do Go e não tem opções sobre as quais discutir. Segundo a Go FAQ, a grande maioria do código Go open source já passou por ele (Go FAQ). Isso torna o Go com que um modelo aprendeu invulgarmente uniforme, e é por isso que o output dos modelos tende a parecer Go idiomático logo à primeira tentativa.
A formatação também ajuda na revisão. Se o modelo errar um detalhe de formatação, o gofmt corrige-o com um comando, por isso os teus diffs mostram alterações de lógica e nunca tabs contra espaços nem a posição das chavetas. Os nomes seguem o mesmo padrão. Os nomes exportados começam com maiúscula, os erros são o último valor devolvido e o context.Context é o primeiro parâmetro de tudo o que faz I/O. Quem revê sabe onde olhar em qualquer ficheiro Go, quer tenha sido escrito por uma pessoa, quer por um modelo.
O compilador revê cada linha primeiro
O compilador de Go rejeita toda uma categoria de erros da IA antes de correr um único teste. Pega nesta função auxiliar que um assistente pode deixar para trás depois de uma refatoração:
example.gogoimport ( "net/http" "strings" ) func countItems(r *http.Request) int { n := 0 items := r.URL.Query()["item"] return len(items) }
Em Go, não compila:
example.texttext./handler.go:5:2: "strings" imported and not used ./handler.go:9:2: declared and not used: n
Os dois erros são o tipo de restos que um modelo deixa quando reescreve uma função a meio: um import de uma tentativa anterior, uma variável de lógica que removeu. O Go torna-os erros de propósito. Troca «conveniência a curto prazo por velocidade de compilação e clareza do programa a longo prazo», e «o compilador de Go não emite avisos, apenas erros que impedem a compilação» (Go FAQ). Como não há nenhum aviso para ignorar, o agente tem de corrigir o problema antes de a compilação passar.
Os tipos estáticos apanham o resto dos deslizes comuns. Passar uma string onde se espera um int64, devolver um valor de uma função que devolve dois ou chamar um método que não existe, tudo isso falha em tempo de compilação. Isso cobre a maior parte do que os modelos erram. Investigadores da ETH Zurich e da UC Berkeley concluíram que cerca de 94 % dos erros de compilação em TypeScript gerado por LLMs eram falhas na verificação de tipos, não erros de sintaxe (Mündler et al., PLDI, 2025). O estudo era sobre TypeScript, e a conclusão aplica-se diretamente ao Go: é no verificador de tipos que se apanham os erros gerados.
A velocidade de compilação do Go torna esta verificação barata. A Go FAQ define como objetivo que «deve demorar no máximo alguns segundos a compilar um executável grande num único computador» (Go FAQ). Um agente que recompila depois de cada alteração corre o compilador dezenas de vezes por tarefa, e compilações rápidas mantêm esse ciclo curto. O ciclo vale a pena: devolver os resultados do compilador a um modelo fez subir a taxa de compilação bem-sucedida de 44,18 % para 89,18 % numa tarefa de completação de código (Wang et al., ACL, 2022).
O código Go que um modelo aprendeu há anos ainda funciona
Um modelo só conhece as APIs que estavam nos seus dados de treino. Com o Go, esse conhecimento não fica desatualizado.
A promessa do Go 1 diz que «os programas escritos segundo a especificação do Go 1 vão continuar a compilar e a correr corretamente, sem alterações, durante toda a vida dessa especificação» (Go 1 compatibility). Código net/http de 2014 ainda compila. Quando um modelo sugere padrões de http.HandleFunc, database/sql ou encoding/json que viu em repositórios antigos, eles funcionam. Todos os repositórios Go públicos desde 2012 continuam a ser dados de treino válidos.
Quando o Go acrescenta uma forma melhor de escrever alguma coisa, a toolchain atualiza o código antigo por ti. A equipa do Go criou os modernizadores do go fix do Go 1.26 em parte a pensar na IA. Alan Donovan escreveu que os assistentes de programação «tendiam (sem surpresa) a produzir código Go num estilo semelhante à massa de código Go usada no treino, mesmo quando havia formas mais novas e melhores de exprimir a mesma ideia» (Go blog, 2026). Correr go fix ./... reescreve esses padrões: interface{} passa a any, for i := 0; i < n; i++ passa a for i := range n, e os limites escritos à mão passam a min e max. Os modernizadores do go fix no Go 1.26 lista todos os analisadores com exemplos de antes e depois.
Uma biblioteca padrão que cobre o backend
A maior parte do que um serviço backend precisa vem com o Go. Servidores e clientes HTTP, routing com métodos e parâmetros de caminho (desde o Go 1.22), JSON, interfaces SQL, TLS, criptografia, testes e logging estruturado com log/slog estão todos na biblioteca padrão. Um modelo consegue construir um serviço de API completo só com linhas de import da biblioteca padrão, e os modelos já viram esses pacotes numa grande quantidade de dados de treino.
Isto importa porque os modelos inventam mesmo pacotes. Um estudo da USENIX Security 2025 sobre 16 modelos concluiu que os modelos comerciais sugeriram pacotes inexistentes em pelo menos 5,2 % das vezes, e os modelos open source em 21,7 %, com 205.474 nomes inventados distintos no total (Spracklen et al., USENIX Security, 2025). Há atacantes a registar esses nomes, um truque a que Seth Larson, developer-in-residence da PSF, chamou «slopsquatting» (Socket, 2025). Cada import de que um modelo não precisa é um import que não pode errar.
Quando um projeto Go acrescenta uma dependência, o sistema de módulos torna-a fácil de rever. Os imports são caminhos completos de repositório, como github.com/jackc/pgx/v5, em vez de nomes curtos, e o go.sum mais a base de dados pública de checksums fixam cada dependência aos bytes exatos. Uma dependência inesperada salta à vista no diff. O Go é mais seguro do que o Node.js? percorre o sistema de módulos em detalhe.
Código explícito é fácil de rever
Quando é um modelo que escreve o código, o teu trabalho passa a ser lê-lo. O estilo explícito do Go, incluindo o tratamento de erros, foi feito para ser lido.
Um agente com um bom prompt escreve um método de repositório e um handler assim:
example.gogovar ErrNotFound = errors.New("user not found") func (s *Store) FindUser(ctx context.Context, id string) (User, error) { var u User err := s.db.QueryRowContext(ctx, `SELECT id, email FROM users WHERE id = $1`, id, ).Scan(&u.ID, &u.Email) if errors.Is(err, sql.ErrNoRows) { return User{}, ErrNotFound } if err != nil { return User{}, fmt.Errorf("find user %s: %w", id, err) } return u, nil } func getUser(users finder) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { u, err := users.FindUser(r.Context(), r.PathValue("id")) switch { case errors.Is(err, ErrNotFound): http.Error(w, "not found", http.StatusNotFound) return case err != nil: slog.Error("get user", "err", err) http.Error(w, "internal error", http.StatusInternalServerError) return } fmt.Fprintf(w, "%s\n", u.Email) } }
Todos os caminhos de saída de cada função estão à vista. Consegues verificar quatro coisas sem abrir outro ficheiro: a query usa o context do pedido, uma linha em falta dá um 404, os outros erros da base de dados ficam registados no log e dão um 500 sem revelar detalhes ao cliente, e o erro encapsulado guarda o ID do utilizador para a linha de log. Não há nenhuma exceção que possa ser lançada noutro sítio e apanhada sabe-se lá onde.
A mesma clareza torna visíveis os erros saltados. Um erro ignorado aparece como uma chamada sem err à esquerda ou com um _ = explícito, e o errcheck (vê a secção de configuração abaixo) assinala os casos fáceis de deixar escapar, como um json.NewEncoder(w).Encode(v) sem verificação. 10 erros comuns em Go a evitar enumera os deslizes no tratamento de erros a que vale a pena estar atento em código gerado.
Concorrência simples de escrever e fácil de verificar
As goroutines, os channels e o context.Context dão ao Go um modelo pequeno e consistente para trabalho concorrente. Um modelo que escreve um worker pool ou um fan-out de chamadas HTTP usa os mesmos poucos blocos de construção que todas as bases de código Go usam, e a toolchain do Go consegue verificar o resultado.
As data races são o bug de concorrência por onde um revisor mais facilmente passa sem reparar. Este middleware de rate limiting, que conta pedidos por chave de API, parece estar bem à primeira vista:
example.gogotype Limiter struct { hits map[string]int max int } func (l *Limiter) Wrap(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { key := r.Header.Get("X-API-Key") l.hits[key]++ if l.hits[key] > l.max { http.Error(w, "too many requests", http.StatusTooManyRequests) return } next.ServeHTTP(w, r) }) }
Os handlers HTTP correm em muitas goroutines ao mesmo tempo, e este map não tem lock. Corremos cinco vezes, no Go 1.27, um teste que envia 50 pedidos concorrentes pelo middleware. O go test -race falhou as cinco com WARNING: DATA RACE e um stack trace a apontar para a linha de l.hits. O detetor de race conditions vem incluído na toolchain e «só encontra races que acontecem em runtime», por isso precisa de um teste que execute o código de forma concorrente (Go race detector). Com esse teste no sítio, um agente que corre go test -race encontra o bug em todas as execuções e pode corrigi-lo com um sync.Mutex.
Ferramentas que o agente consegue correr sozinho
Tudo o que um agente precisa para verificar o próprio trabalho vem no comando go. Não há nada para instalar nem configurar primeiro.
O go vet «examina código-fonte Go e reporta construções suspeitas» que compilam mas que provavelmente estão erradas (cmd/vet). Um deslize típico da IA é um verbo de formatação que não corresponde ao argumento:
example.gogofunc showUser(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") fmt.Fprintf(w, "user %d", id) }
example.texttexthandler.go:10:23: fmt.Fprintf format %d has arg id of wrong type string
O go test corre automaticamente um subconjunto dessas verificações do vet, por isso um agente que corre os testes recebe-as de graça. O go build compila por omissão para um único binário com linkagem estática (Go FAQ), por isso o agente consegue compilar e correr o serviço que acabou de alterar sem ter de preparar um ambiente para isso.
A equipa do Go também está a construir diretamente para agentes. O gopls, o language server do Go, inclui desde a v0.20 «um servidor experimental integrado para o Model Context Protocol (MCP)» (gopls MCP). Um agente ligado a ele consegue pedir definições, referências e diagnósticos ao mesmo motor que o teu editor usa, em vez de adivinhar a partir do texto.
Como preparar um repositório Go para agentes de programação com IA
Um repositório Go recebe a maior parte da sua rede de segurança contra erros da IA da toolchain padrão. A configuração serve para garantir que o agente a corre sempre.
1. Escreve as verificações num ficheiro de instruções para o agente. A maioria dos agentes de programação lê um ficheiro CLAUDE.md ou AGENTS.md na raiz do repositório. O AGENTS.md é hoje gerido pela Agentic AI Foundation, sob a Linux Foundation, e usado por mais de 60.000 projetos open source (agents.md, 2026). Mantém-no curto e concreto:
example.markdownmarkdown## Checks (run before every commit) - go build ./... - go vet ./... - go test -race ./... - golangci-lint run ## Conventions - Standard library first. Ask before adding a dependency. - Wrap errors with fmt.Errorf("context: %w", err). Never discard an error. - Pass context.Context as the first argument to anything that does I/O.
2. Acrescenta o golangci-lint. Junta mais de uma centena de linters, incluindo o errcheck para erros ignorados e o staticcheck, atrás de um só comando. Um agente recebe uma única lista de falhas para corrigir em vez de cinco ferramentas.
3. Mantém testes em tabela perto do código. São os testes mais fáceis de um agente estender corretamente, porque acrescentar um caso é acrescentar uma linha:
example.gogofunc TestGetUser(t *testing.T) { tests := []struct { name string finder fakeFinder wantCode int }{ {"found", fakeFinder{user: User{ID: "42", Email: "[email protected]"}}, http.StatusOK}, {"missing", fakeFinder{err: ErrNotFound}, http.StatusNotFound}, {"db down", fakeFinder{err: errors.New("connection refused")}, http.StatusInternalServerError}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mux := http.NewServeMux() mux.HandleFunc("GET /users/{id}", getUser(tt.finder)) rec := httptest.NewRecorder() mux.ServeHTTP(rec, httptest.NewRequest("GET", "/users/42", nil)) if got := rec.Result().StatusCode; got != tt.wantCode { t.Errorf("status = %d, want %d", got, tt.wantCode) } }) } }
Escreve tu os dois primeiros casos para que o agente copie a tua intenção. Depois pede-lhe que acrescente os casos limite e lê o que ele acrescenta.
4. Corre o -race no CI. Com um agente a escrever código concorrente, o detetor de race conditions é a verificação que mais queres ter em cada push.
5. Corre o go fix depois de grandes alterações geradas. Passa os idiomas antigos para os atuais antes de se espalharem pela base de código.
Nada disto substitui ler o diff. Significa que, quando o leres, o compilador, o go vet, o linter e o detetor de race conditions já rejeitaram os erros mecânicos, e o que sobra é uma questão de critério: este é o design certo, e trata os casos que importam?
Onde entra o LevelUpGo
Deixar a IA escrever Go funciona melhor quando sabes rever Go. Tens de reparar no context ignorado, no lock em falta e no erro que é engolido. O LevelUpGo ensina isso pondo-te a escrever o código tu próprio: cada lição mostra o conceito à esquerda e um editor a sério à direita, e o teu código tem de compilar e passar em testes reais para avançares. Começa pelo curso Go Basics, que é grátis, ou vê o roadmap de Go completo. Para o lado de quem aprende na questão da IA, Ainda deves escrever código à mão? explica quando vale a pena escreveres tu o código, e Vale a pena aprender Go em 2026? trata do argumento de carreira.
Perguntas frequentes
O Go é bom para código gerado por IA?
Sim, e para serviços backend, CLIs e infraestrutura é a melhor escolha. O Go é suficientemente pequeno para que o output dos modelos se mantenha previsível, o gofmt mantém todos os ficheiros num só estilo, o compilador rejeita imports e variáveis não usados, e o go vet e o go test -race apanham bugs que compilam. Mais erros da IA falham automaticamente, e sobra menos para um revisor humano apanhar.
Porque é que o Go é fácil de escrever para os modelos de IA?
O Go tem 25 palavras-chave, um formatador oficial e uma biblioteca padrão que cobre a maior parte do trabalho de backend. Há poucas formas de resolver um dado problema, por isso o output de um modelo parece-se com o Go idiomático com que aprendeu. Os autores do Multi-SWE-bench também concluíram que o Go está entre as linguagens com menor consumo de tokens, o que atribuíram à sua sintaxe minimalista e às suas convenções claras.
O Go é melhor do que Python para agentes de programação com IA?
Para serviços que correm em produção, sim. O Go dá a um agente tipos estáticos, um compilador sem avisos, um detetor de race conditions incluído e um único formatador, sem configuração extra. Essas verificações transformam muitos dos quase acertos que as ferramentas de IA produzem em falhas de compilação que o agente corrige sozinho.
Os modelos de IA inventam pacotes Go?
O principal estudo sobre pacotes inventados, de Spracklen et al. (USENIX Security 2025), testou Python e JavaScript, por isso não há uma taxa publicada para Go. A biblioteca padrão do Go cobre mais de um backend típico, o que significa menos imports que um modelo possa errar, e os caminhos de import completos mais o go.sum tornam uma dependência inesperada fácil de ver na revisão.
Como faço para um agente de IA escrever melhor Go?
Dá-lhe verificações que consiga correr. Põe go build ./..., go vet ./..., go test -race ./... e golangci-lint run num ficheiro CLAUDE.md ou AGENTS.md. Mantém testes em tabela que o agente consiga estender e corre go fix ./... para atualizar idiomas desatualizados. Depois lê tu o diff.
Fontes
- Stack Overflow Developer Survey 2025, secção de IA
- Zan et al., "Multi-SWE-bench," NeurIPS (2025)
- GitHub Octoverse 2025
- Mündler et al., "Type-Constrained Code Generation with Language Models," PLDI (2025)
- Wang et al., "Compilable Neural Code Generation with Compiler Feedback," ACL (2022)
- Spracklen et al., "We Have a Package for You!" USENIX Security (2025)
- Socket, "Slopsquatting" (2025)
- Go FAQ
- Go 1 and the Future of Go Programs
- The Go Programming Language Specification
- cmd/vet
- Data Race Detector
- Alan Donovan, "Using go fix to modernize Go code," Go blog (2026)
- Servidor MCP do gopls
- Claude Code best practices
- AGENTS.md
