- Esta versão melhora literais de struct e inferência de tipos com foco em métodos genéricos, além de adicionar recursos práticos à biblioteca padrão, ao runtime e à toolchain
- Com alocação de memória especializada por tamanho, o custo de algumas alocações abaixo de 80 bytes cai em até 30%; em programas intensivos em alocação, espera-se cerca de 1% de ganho de desempenho e aumento de cerca de 60 KB no binário
encoding/json/v2passa a ser oferecido oficialmente, e oencoding/jsonexistente também usa internamente o v2; foram adicionados o pacote padrão de UUID e assinaturas ML-DSA baseadas em FIPS 204- O perfil
goroutineleak, rótulos do pprof em traceback,synctest.Sleeppara tempo virtual e um servidor HTTP de teste em memória facilitam diagnóstico e testes de concorrência - Canais de timer sem buffer, drenagem automática do corpo de resposta HTTP e restrições mais rígidas em
//go:linknamepodem afetar código existente, então é preciso verificar a compatibilidade antes da migração para o Go 1.27
Linguagem e sistema de tipos
- O principal destaque do Go 1.27, os métodos genéricos, permitem declarar parâmetros de tipo próprios, independentes do receiver
- Antes, só funções de nível superior podiam ser genéricas, então até operações ligadas a tipos precisavam ser escritas como funções de pacote
- Agora é possível definir como método operações como
Box[T].Map[U], que retornam um tipo de elemento diferente do de entrada - Interfaces ainda não podem declarar métodos com parâmetros de tipo, e também não é possível implementar interfaces com métodos genéricos
- As chaves de literais de struct agora podem usar não só nomes de campos de nível superior, mas também seletores de campo válidos
- Em structs embutidas, campos promovidos podem ser inicializados diretamente, como em
User{ID: 7}
- Em structs embutidas, campos promovidos podem ser inicializados diretamente, como em
- A inferência de tipos de função foi ampliada para conversões e literais compostos
- Em
[]func([]int) int{first, last}, os argumentos de tipo de funções genéricas são inferidos com base no tipo de função esperado - Antes, era necessário instanciar explicitamente, como em
first[int]elast[int]
- Em
Runtime e desempenho
- O compilador passa a chamar rotinas de alocação especializadas por tamanho, reduzindo em até 30% o custo de algumas alocações de memória menores que 80 bytes
- Em programas reais intensivos em alocação, o ganho total esperado de desempenho é de cerca de 1%
- Não exige alterações no código, mas o binário cresce cerca de 60 KB independentemente da carga de trabalho
- Pode ser desativado com
GOEXPERIMENT=nosizespecializedmalloc, mas essa opção será removida no Go 1.28
- Foram adicionadas três otimizações de compilador ativadas por padrão
- Um pass de fluxo de dados de bits conhecidos que rastreia bits sabidamente 0 ou 1 para eliminar operações redundantes
- Movimentação de código invariante de laço, que leva para fora do loop cálculos que não mudam durante a repetição
- Compilação de
switchcompatíveis em tabelas de consulta, incluindofallthrough
- O experimental
GOEXPERIMENT=mapsplitgroupaltera o layout de memória de grupos de map deKVKVKVKVparaKKKKVVVV, mas permanece desativado por padrão - O linker move descritores de tipo e itabs para uma seção dedicada
.go.typee removetypelinkseitablinks- Como
reflect.typelinkspassa a retornar tipos em vez de offsets, bibliotecas que acessam esse símbolo via//go:linknamepodem ser afetadas
- Como
Diagnóstico de goroutines e profiling
- Módulos cujo
go.modindica Go 1.27 ou superior passam a mostrar rótulos deruntime/pprofno cabeçalho de goroutines em traceback- Contextos anexados com
pprof.Do, como{request: 42}, aparecem em crash dumps,SIGQUITe na saída deruntime.Stack - Para evitar que rótulos sensíveis apareçam em traceback, continua possível usar
GODEBUG=tracebacklabels=0
- Contextos anexados com
- O detector de vazamento de goroutines, que era experimental no Go 1.26, foi promovido ao perfil oficial
goroutineleak- Ele executa GC para encontrar goroutines que nunca poderão progredir, como em canais ou mutexes, e imprime as pilhas
- Em serviços, pode ser coletado pelo endpoint
/debug/pprof/goroutineleaksem necessidade deGOEXPERIMENT
Criptografia e identificadores
- O novo pacote crypto/mldsa implementa a assinatura pós-quântica ML-DSA do FIPS 204
- Os três conjuntos de parâmetros
MLDSA44,MLDSA65eMLDSA87equilibram tamanho de chave/assinatura e nível de segurança - ML-DSA também foi adicionado a chaves e assinaturas de
crypto/x509e aos esquemas de assinatura TLS 1.3 decrypto/tls
- Os três conjuntos de parâmetros
- O novo pacote padrão uuid gera e analisa UUIDs RFC 9562 com números aleatórios criptograficamente seguros
uuid.New()escolhe um método adequado para uso geral,NewV4()gera UUID puramente aleatório eNewV7()gera UUIDs em ordem de criação- UUIDs compostos por parte aleatória são comparáveis, então
==pode ser usado diretamente - UUID v7, ordenável por tempo, é adequado para chaves de banco de dados
APIs de JSON e processamento de dados
- encoding/json/v2 e o
encoding/json/jsontextde baixo nível são disponibilizados semGOEXPERIMENT=jsonv2- O
encoding/jsonv1 existente também passa a usar internamente a implementação v2 - Exceto por parte do texto de algumas mensagens de erro, o comportamento anterior é mantido, então não é necessária migração
- Se houver problema de compatibilidade, é possível restaurar a implementação original v1 com
GOEXPERIMENT=nojsonv2 - Por desempenho, o v2 não ordena chaves de map por padrão, então testes que exigem saída estável devem definir
json.Deterministic
- O
strings.CutLastebytes.CutLastdividem um valor com base no último delimitador- Se não houver delimitador, retornam a entrada inteira, uma parte final vazia e
false
- Se não houver delimitador, retornam a entrada inteira, uma parte final vazia e
- O genérico
Hasher[T]dehash/maphashdefine em conjunto a estratégia de hash e igualdade de valores- Valores iguais devem obrigatoriamente ter o mesmo hash
- É fornecido
ComparableHasher[T]para tipos comparáveis, e também é possível implementar estratégias customizadas, como strings case-insensitive
math/big.Int.Dividecalcula quociente e resto ao mesmo tempo, aplicando um modo de arredondamento explícito entreTrunc,Floor,RoundeCeil- Como o resto também muda conforme o arredondamento, isso complementa em código financeiro e numérico a limitação de truncamento em direção a zero de
QuoeMod
- Como o resto também muda conforme o arredondamento, isso complementa em código financeiro e numérico a limitação de truncamento em direção a zero de
math/rand/v2.(*Rand).Ngera números aleatórios limitados por faixa para tipos inteiros arbitrários ou duration, usando sua própria fonte*Rand
SIMD portável
- O pacote experimental simd oferece uma API SIMD independente do tamanho do vetor e é ativado com
GOEXPERIMENT=simd- Em ambientes compatíveis, ele é compilado para instruções vetoriais reais de hardware; caso contrário, usa emulação pura em Go
- O número de lanes de tipos como
Float32snão é fixo e segue a largura de hardware de cada máquina
- A biblioteca padrão já usa internamente intrinsics
simd/archsimdMemHash32,MemHash64eStrHashdo map Swiss Table foram reimplementados com a nova base SIMD
Testes determinísticos
testing/synctest.Sleepavança o tempo virtual e espera até que todas as goroutines estabilizem em uma só operação- Dentro de um bubble do
synctest, o tempo real não passa, então até uma espera de 2 segundos termina imediatamente - Isso substitui código repetitivo que combinava
time.Sleepcomsynctest.Wait
- Dentro de um bubble do
httptest.NewTestServerexecuta o servidor em uma rede virtual em memória em vez de uma porta TCP realsrv.Client()se conecta diretamente ao handler por pipes internos ao processo- Como a limpeza é automática com
t.Cleanup, não é necessáriodefer srv.Close() - Combinado com
testing/synctest, isso permite testar ida e volta HTTP em tempo virtual com rapidez e determinismo
Rede e mudanças de compatibilidade
- Os canais retornados por
time.After,time.NewTimer,time.NewTickere afins passam a ser sempre canais síncronos sem buffer- A opção
asynctimerchande GODEBUG, que restaurava o comportamento antigo com buffer, foi removida
- A opção
- Em HTTP/1,
http.Response.Body.Closelê de forma conservadora o corpo ainda não consumido para ajudar no reaproveitamento da conexão- Se você dependia de
Closepara encerrar cedo downloads grandes, será necessário desativar o reúso comTransport.DisableKeepAlives
- Se você dependia de
- Servidores HTTP/2 passam a entender prioridades de cliente da RFC 9218 e processam primeiro streams de maior prioridade
- É possível restaurar o comportamento anterior round-robin com
Server.DisableClientPriority = true
- É possível restaurar o comportamento anterior round-robin com
crypto/x509.SystemCertPoolno Windows e no macOS passa a oferecer suporte aSSL_CERT_FILEeSSL_CERT_DIR- Quando essas variáveis estão definidas, certificados raiz do disco são lidos e o verificador do Go é usado no lugar da API da plataforma
- Isso pode ser desativado com
GODEBUG=x509sslcertoverrideplatform=0
- A implementação de HTTP/2, antes incluída no arquivo gerado de 12.226 linhas
h2_bundle.go, foi substituída por um pacote realnet/http/internal/http2 - Foram adicionados ao
net/httphooks de HTTP/3 plugáveis ainda pré-públicos, e parte da suíte de testes já roda sobre HTTP/3- Ainda não existe API pública utilizável, mas a base para um futuro
http.Transportsobre QUIC já está incluída
- Ainda não existe API pública utilizável, mas a base para um futuro
Toolchain
go testpassa a executar por padrão a verificação de vetstdversion, que procura uso de símbolos da biblioteca padrão mais novos que a versão de Go declarada emgo.modgo doc pkg@versionpermite consultar a documentação de uma versão específica de módulogo doc -exlista exemplos executáveis, e ao indicar diretamente o nome do exemplo exibe seu código-fontego fixganha os analisadores de modernizaçãoatomictypes,embedlit,slicesbackwardeunsafefuncswaitgroupfoi renomeado parawaitgroupgoefmtappendffoi removido
- Em módulos Go 1.27+,
go mod tidyconsolida blocosrequiredispersos em dois blocos, um para dependências diretas e outro para indiretas, preservando comentários go tool trace -http=:6060passa a bindar apenas em localhost quando apenas a porta é informada; para acesso externo, é preciso especificar o endereço- O comando
goremove o suporte ao sistema de controle de versão Bazaar (bzr) compile,link,asm,cgo,coverepackpassam a oferecer suporte a arquivos de resposta (@file) no formato GCC para evitar limites de tamanho de linha de comando
Unicode e fronteiras de segurança
- Os dados Unicode da biblioteca padrão foram atualizados de Unicode 15 para Unicode 17
- Caracteres adicionados no Unicode 16 também passam a ser classificados corretamente como símbolos ou caracteres imprimíveis
- Foi corrigido um problema que permitia escapar para fora da raiz usando
os.Root.ReadDireReaddir - O uso não autorizado de
//go:linknameficou mais difícil- A diretiva
linknamestdmarca linknames que só a biblioteca padrão pode importar - Como o linker também passa a verificar acesso por linkname a símbolos de assembly, código que depende de símbolos internos não oficiais precisa ser testado antecipadamente
- A diretiva
1 comentários
Comentários no Lobste.rs
Talvez seja o melhor release de todos os tempos. SIMD, uuid, jsonv2 finalmente chegaram
Fugindo um pouco do tema, este é um bom exemplo de como surgem bugs quando tudo é tratado como string e não se considera os contratos e as relações entre métodos de interface
Equalignora maiúsculas e minúsculas, masHashusa o valor convertido para minúsculas. Porém,EqualFoldeToLowernão definem a mesma relação de equivalênciahttps://github.com/golang/go/issues/52204
"\u017F"(ſ, s longo) e"s"são iguais emEqualFold, mas o resultado deToLowerpara cada um é diferente. Assim, se você inserir"s"e depois"ſ", os hashes serão diferentes e isso fará com que sejam inseridos como itens separadosO mais curioso é que a documentação alerta exatamente sobre esse caso
https://github.com/golang/go/…
https://github.com/golang/go/…
Bom ver outra pessoa continuando de onde Anton parou
Gosto de Go, mas fico em dúvida se a sintaxe de Go é elegante o bastante para continuar acrescentando esse tipo de recurso a cada release
func (b Box[T]) Map[U any](f func(T) U) Box[U] {Já a verbosidade de Go e Zig tem a vantagem de não obrigar você a rolar para outro lugar para encontrar a definição do receiver. No ponto de chamada, que dá para considerar mais importante do que a própria definição, todas acabam parecendo quase iguais e nem exigem explicitar o tipo
Faz tempo que eu estava longe de Go, e jsonv2 parece promissor. Mas, se virar o padrão, fico me perguntando se isso não quebraria a promessa de compatibilidade que Go mantém há tanto tempo
encoding/json/v2, então é algo que você escolhe explicitamente. Oencoding/jsonexistente usa v2 internamente, mas preserva o comportamento anterior, e o jsonv2 também traz flags para reproduzir os comportamentos excepcionais da v1, então isso não quebra a promessa de compatibilidade