trilha

Tecnologias/01 - Linguagens/01 - Go6 min

Versões, Módulos e Compatibilidade

Conceito

Quando uma vaga pede "Go 1.27", ela quase nunca está pedindo uma feature específica de 1.27 — está dizendo "usamos Go atual, não um projeto parado em 1.16". Vale entender o mecanismo por trás disso, porque ele é incomum entre linguagens.

O ciclo: duas releases por ano, sempre

Go lança em fevereiro e agosto, na data, com o que estiver pronto. Nada de esperar uma feature grande.

Versão Data
Go 1.26.0 10/02/2026
Go 1.27.0 19/08/2026
Go 1.27.1 01/09/2026

Suporte: as duas majors mais recentes recebem correções de segurança. Hoje, isso é 1.27 e 1.26 — o 1.25 já saiu da janela. É por isso que "estar em Go atual" é uma exigência de segurança, não de moda.

A promessa de compatibilidade Go 1

Código que compila com Go 1.x continua compilando e funcionando em Go 1.y (y > x).

Essa é a promessa mais valiosa e mais caríssima do Go. Ela é o motivo de:

  • atualizar a toolchain ser rotina, não projeto;
  • interface{} continuar existindo depois de any;
  • decisões ruins de 2012 (o pacote math/rand v1, a API de time.After) nunca terem sido corrigidas — só duplicadas em v2.

E existe uma válvula de escape para quando o comportamento precisa mudar: GODEBUG. Se uma correção de bug pode quebrar programas que dependiam do bug, o Go mantém o comportamento antigo acessível por GODEBUG=algo=1, e usa a diretiva go do go.mod para decidir o padrão. Ou seja: a sua go.mod seleciona a semântica, não só a sintaxe.

Módulos: MVS, não resolução de ranges

Aqui o Go difere de npm, pip e Maven de um jeito importante:

go.mod  → requisitos mínimos declarados
go.sum  → hash de tudo, verificável

O algoritmo é MVS (Minimal Version Selection): para cada dependência, o Go escolhe a maior das versões mínimas exigidas por alguém no grafo. Não existe intervalo (^1.2), não existe resolvedor SAT, não existe "atualizou sozinho na CI".

Go (MVS) npm/Cargo (ranges)
Build reprodutível por construção precisa de lockfile
Atualização só explícita (go get -u) pode acontecer no install
Seleção de versão uma versão por caminho de módulo; compatibilidade ainda precisa ser verificada resolvedor considera os requisitos declarados
Dois majors juntos permitido (/v2 no path) por nesting

Trade-offs

A promessa Go 1 é uma dívida acumulada. A biblioteca padrão carrega APIs que ninguém recomenda mais, e o preço aparece na forma de v2 convivendo com v1 (math/rand/v2, encoding/json/v2). Você precisa saber qual está usando.

GODEBUG esconde mudanças de comportamento. É o que permite evoluir sem quebrar — e também o que faz um programa mudar de comportamento só por você ter subido a diretiva go no go.mod, sem trocar uma linha de código.

MVS é conservador de propósito. Você fica em versões antigas até pedir para sair. Ótimo para reprodutibilidade, ruim para receber correções de segurança sem esforço — daí govulncheck e Dependabot serem parte do fluxo, não luxo.

O trade-off central: Go escolheu estabilidade sobre limpeza. Todo desconforto de API na biblioteca padrão é o preço de você poder atualizar a toolchain numa terça-feira à tarde.

Exemplo prático

O que o Go 1.27 trouxe

Linguagem

  • Métodos genéricos: um método pode declarar os próprios parâmetros de tipo (ex.: (*Rand).N[Int intType](Int) Int em math/rand/v2). Interfaces continuam sem poder declarar métodos genéricos.
  • Chaves em literais de struct podem ser qualquer seletor de campo válido, não só nomes de campo do topo — funciona bem com embedding.
  • Inferência de tipo generalizada: vale agora em todo contexto onde uma função genérica é atribuída a variável ou convertida para um tipo de função compatível.

Biblioteca

  • encoding/json passou a ser implementado pela v2 por padrão. Novos pacotes: encoding/json/v2 (API com Options variádicos) e encoding/json/jsontext (nível sintático). Saída de emergência: GOEXPERIMENT=nojsonv2.
  • Pacote uuid na biblioteca padrão: gera e faz parse de UUID.
  • crypto/mldsa: ML-DSA (FIPS 204), assinatura pós-quântica, com suporte em crypto/x509.

Runtime e diagnóstico

  • Perfil goroutineleak agora estável em runtime/pprof e em /debug/pprof/goroutineleak. Ver 2. Goroutines e Channels.
  • Alocação especializada por tamanho: alocações pequenas (< 80 bytes) até 30% mais baratas; binário cresce ~60 KB. Saída: GOEXPERIMENT=nosizespecializedmalloc (deve sair no 1.28).
  • GODEBUG=asynctimerchan foi removido: canais do pacote time são sempre sem buffer.
  • SIMD experimental (simd/archsimd) ganhou arm64 Neon e WebAssembly.

Ferramentas

  • go test roda o vet stdversion por padrão.
  • go doc aceita pacote@versão e tem -ex para listar exemplos executáveis.
  • go fix ganhou modernizadores (atomictypes, embedlit, slicesbackward, unsafefuncs); waitgroup virou waitgroupgo.
  • go mod tidy reorganiza os require em dois blocos (diretas e indiretas).
  • go tool trace -http agora escuta só em localhost por padrão.
  • O go não suporta mais bzr.

JSON no 1.27: implementação e contrato público

O pacote encoding/json passa a usar a implementação v2, preservando o comportamento de marshal/unmarshal da API v1. O texto exato de erros pode mudar. Já usar diretamente encoding/json/v2 adota padrões mais estritos, salvo opções explícitas de compatibilidade:

Entrada API encoding/json API encoding/json/v2, padrões próprios
UTF-8 inválido numa string aceitava (substituía) rejeita
Nome duplicado no objeto ({"a":1,"a":2}) aceitava (último vence) rejeita

Ao migrar explicitamente para a API v2, teste mensagens de produtores legados e histórico de Kafka. Rejeitar uma entrada passa a ser decisão do parser; traduzir o erro em resposta HTTP é responsabilidade da aplicação. Atualizar a toolchain mantendo a API v1 não deve ser descrito como adoção automática dos padrões estritos da v2. Referência: notas oficiais do Go 1.27.

Checklist de atualização de toolchain

go version                     # onde estou
go get go@1.27.1               # sobe a diretiva go e a toolchain
go mod tidy                    # no 1.27, também reorganiza os require
go build ./... && go test ./... # o de sempre
go vet ./...                   # stdversion agora roda no go test também
govulncheck ./...              # o passo que a maioria esquece
GOEXPERIMENT=nojsonv2 go test ./...  # se algo de JSON quebrou, confirma a causa
A diretiva go do go.mod não é decoração

Ela define (a) qual sintaxe da linguagem é permitida e (b) quais padrões de GODEBUG valem. Subir de go 1.21 para go 1.27 pode mudar comportamento de runtime. Suba de propósito, num commit só seu, com os testes ao lado.

Aprofundamento aplicado

MVS em um grafo concreto

aplicação exige biblioteca A v1.2
aplicação exige biblioteca B v1.0
B v1.0 exige A v1.4
versão selecionada de A: v1.4

A seleção satisfaz a maior exigência mínima. Isso não prova que A v1.4 respeitou todos os contratos comportamentais usados pela aplicação. Um fornecedor pode introduzir uma regressão dentro do mesmo major; por isso a seleção determinística não substitui testes.

go.sum registra verificações de conteúdo e pode listar versões que não participam do build atual. Para entender a seleção, examine go list -m all e go mod graph. Um replace local também pode alterar o código compilado sem representar o que um consumidor externo da biblioteca obterá. Referência: seleção de versões e replace.

Exercício: desenhe três módulos com exigências diferentes para uma dependência. Resultado esperado: consiga prever a versão selecionada e explicar separadamente como verificar integridade, compatibilidade e a versão da toolchain.

Relacionado


Parte de MOC Go · go.dev/doc/go1.27 · Histórico de releases

Buscar

Busca por título, seção e texto das notas