Desde o Go 1.18 (lá em 2022), a linguagem suporta generics. Mas com uma limitação que irritava todo mundo: você podia declarar tipos genéricos e funções genéricas, mas não podia ter um método com seus próprios type parameters. Se você quisesse um método genérico numa struct, precisava criar uma função standalone no pacote, quebrando a ergonomia do código.
No Go 1.27, isso acabou. Agora métodos podem declarar seus próprios type parameters:
type Stack[T any] struct {
items []T
}
func (s *Stack[T]) Map[U any](fn func(T) U) []U {
result := make([]U, len(s.items))
for i, item := range s.items {
result[i] = fn(item)
}
return result
}
Percebe a diferença? O método Map tem seu próprio tipo U, independente do T da struct. Antes do 1.27, você teria que escrever uma função Map<a href="s *Stack[T], fn func(T">T, U any</a> U) []U no nível do pacote, perdendo a associação com o tipo.
Tem uma restrição importante: métodos de interface não podem declarar type parameters, e métodos genéricos não podem implementar métodos de interface. Faz sentido, já que a resolução dinâmica de interfaces não combina bem com a monomorphization de generics. Mas pra 95% dos casos de uso, a feature resolve.
Isso abre portas para patterns como builders fluentes genéricos, pipelines de transformação tipados e DSLs internas que antes eram impossíveis ou extremamente verbosas em Go.
Outra mudança de linguagem que passou despercebida: struct literals agora aceitam field selectors aninhados como chaves. Antes, se você tinha uma struct com campos aninhados, precisava inicializar cada nível separadamente. Agora:
type Config struct {
Server struct {
Port int
}
}
// Go 1.27: inicialização direta
cfg := Config{Server.Port: 8080}
Parece açúcar sintático, e é. Mas reduz boilerplate em structs de configuração profundamente aninhadas, que são extremamente comuns em projetos Go maiores.
A terceira mudança de linguagem é a generalização da inferência de tipos de função. Agora, quando você atribui uma função genérica a uma variável com tipo de função compatível, o compilador infere os type parameters automaticamente em qualquer contexto, não apenas em chamadas diretas. Menos [int] explícito no código, mais ergonomia.
encoding/json/v2: a reescrita que levou 6 anos
Se existe uma queixa universal entre devs Go, é o pacote encoding/json. Lento, cheio de comportamentos bizarros, e com defaults que ninguém pediu. A proposta do json/v2 existe desde 2020, e finalmente está na standard library.
O novo encoding/json/v2 vem com mudanças que parecem óbvias, mas que o v1 nunca fez:
| Comportamento | json v1 | json v2 | |
|---|---|---|---|
| — | — | — | |
| UTF-8 inválido em strings | Aceita silenciosamente | Rejeita com erro | |
| Nomes duplicados em objetos | Aceita o último | Rejeita com erro | |
| Performance de unmarshal | Baseline | Significativamente mais rápido | |
| Configurabilidade | Tags de struct | Options variádico |
A API mudou pouco na superfície. Você ainda tem Marshal e Unmarshal, mas agora com variantes como MarshalWrite e UnmarshalRead que operam diretamente em io.Writer e io.Reader. Todas as funções aceitam Options variádicos para configuração granular.
import "encoding/json/v2"
data, err := json.Marshal(myStruct, json.Options{
// configurações aqui
})
O detalhe mais interessante: o pacote encoding/json original (v1) agora é backed pelo v2 por baixo dos panos. Ou seja, mesmo que você não mude nada no seu código, já vai rodar com a implementação nova. Se por algum motivo isso quebrar algo (improvável, mas possível), dá para desligar com GOEXPERIMENT=nojsonv2 na build.
Junto com o json/v2, veio o encoding/json/jsontext, um pacote de baixo nível para processamento sintático de JSON. Ele expõe Encoder e Decoder que operam com Token e Value, mantendo uma máquina de estados para validar que o JSON produzido é estruturalmente correto. Se você escreve parsers customizados ou streaming de JSON, esse pacote é ouro.
UUID nativo: chega de dependência externa
Eu sei que parece pouca coisa, mas qualquer dev Go que já precisou de um UUID sabe a dor. Ou você importava github.com/google/uuid, ou github.com/gofrs/uuid, ou escrevia na mão com crypto/rand. Nenhuma opção era ideal.
Go 1.27 traz o pacote uuid na standard library. Geração e parsing de UUIDs sem dependências externas. Pronto. Funciona. Acabou o debate.
É o tipo de adição que parece trivial até você perceber que UUID é usado em literalmente todo microsserviço, todo banco de dados, toda API. Ter isso na stdlib significa menos uma dependência no go.mod de todo projeto Go do planeta.
Criptografia pós-quântica no TLS 1.3
Enquanto a maioria dos devs está preocupado com deadlines e PRs, o time de criptografia do Go está pensando em computadores quânticos. O Go 1.27 adiciona suporte a ML-DSA (Module-Lattice Digital Signature Algorithm, definido no FIPS 204) na stack de TLS.
Na prática, isso significa:
- O pacote
crypto/mldsaimplementa assinaturas ML-DSA - O
crypto/x509suporta chaves privadas, chaves públicas e assinaturas ML-DSA - O
crypto/tlsaceita assinaturas ML-DSA no TLS 1.3, com três schemes:MLDSA44,MLDSA65eMLDSA87 - Key exchange com
MLKEM1024(ML-KEM, o outro algoritmo pós-quântico) também está disponível
Você provavelmente não vai usar isso amanhã. Mas daqui a 5 anos, quando computadores quânticos começarem a quebrar RSA e ECDSA, o Go já vai estar preparado. E se você trabalha com governo, fintech ou qualquer sistema que precisa de compliance futura com FIPS, essa feature já é relevante hoje.
Goroutine leak profiler: debug sem dor de cabeça
Goroutine leaks são o memory leak do Go. Fáceis de criar, difíceis de detectar, e quando você percebe já tem 500 mil goroutines paradas em um <-chan que ninguém vai fechar.
O Go 1.27 traz o goroutine leak profile como feature GA (General Availability). Ele usa análise de alcançabilidade do garbage collector para identificar goroutines bloqueadas em primitivas de concorrência inalcançáveis. Traduzindo: se uma goroutine está esperando em um channel que ninguém mais tem referência, o profiler detecta.
# Via endpoint HTTP
curl http://localhost:6060/debug/pprof/goroutineleak
# Via runtime/pprof no código
pprof.Lookup("goroutineleak").WriteTo(w, 1)
Essa feature existia como experiment desde o Go 1.26, mas agora está estável. Se você roda serviços Go em produção (e quem não roda?), adicione esse endpoint ao seu monitoring. Sério.
SIMD experimental: performance na veia
Essa é para quem lida com processamento pesado. O Go 1.27 adiciona o pacote simd (experimental, precisa de GOEXPERIMENT=simd) com operações SIMD portáveis e agnósticas ao tamanho do vetor.
import "simd"
// Operações vetorizadas
var a, b simd.Float32s
result := simd.Add(a, b)
O pacote funciona em todas as arquiteturas, com aceleração por hardware onde disponível. Pra quem precisa de mais controle, o simd/archsimd oferece operações específicas por arquitetura: Neon no ARM64, SSE/AVX no AMD64, e SIMD de 128 bits no WebAssembly.
A API é explicitamente marcada como instável, então não coloque em produção ainda. Mas pra quem trabalha com processamento de áudio, vídeo, machine learning ou criptografia, é um sinal claro de que o Go está levando performance computacional a sério.
Alocação de memória 30% mais rápida
Uma melhoria que não aparece no changelog com pompa, mas que impacta todo programa Go: o compilador agora gera rotinas de alocação especializadas por tamanho. Objetos pequenos (menos de 80 bytes) alocam até 30% mais rápido.
Na média, programas com muitas alocações ganham aproximadamente 1% de performance geral. Não parece muito, mas em serviços que processam milhões de requests por segundo, 1% é dinheiro no bolso.
O custo é um aumento de ~60 KB no binário. Se por algum motivo isso for um problema (embedded?), desative com GOEXPERIMENT=nosizespecializedmalloc.
Junto com isso, o HTTP/1 ganhou auto-drain de response bodies ao fechar a conexão. Parece detalhe de implementação, mas na prática significa que conexões TCP são reutilizadas com mais eficiência. Se você tem um serviço que faz muitos requests HTTP para APIs externas, vai notar menos sockets em TIME_WAIT.
Melhorias na standard library que ninguém vai noticiar
Além das features headline, o Go 1.27 tem dezenas de melhorias menores que facilitam o dia a dia:
bytes e strings: nova função CutLast que corta a string ao redor da última ocorrência do separador. Quem já escreveu s[:strings.LastIndex(s, sep)] sabe a falta que isso fazia.
net/http: o body de respostas HTTP/1 agora faz auto-drain ao fechar. Isso melhora a reutilização de conexões sem que você precise ler o body inteiro manualmente. O servidor HTTP/2 também passou a aceitar sinais de prioridade do cliente (RFC 9218).
net/http/httptest: novo NewTestServer que cria um servidor com rede fake in-memory, compatível com o pacote testing/synctest. Testes de HTTP ficaram mais determinísticos.
database/sql: nova função ConvertAssign que dá aos drivers acesso às conversões de tipo usadas pelo Rows.Scan. E a interface RowsColumnScanner permite scanning direto para o destino do usuário, evitando alocações intermediárias.
math/big: novo método Int.Divide que computa quociente e resto com suporte a modos de arredondamento (Trunc, Floor, Round, Ceil). Quem trabalha com cálculos financeiros em Go vai agradecer.
go doc: agora suporta package@version (tipo go doc example.com/pkg@v1.2.3) e a flag -ex lista exemplos executáveis. Pequeno, mas muda a vida de quem consulta documentação no terminal.
Unicode 17: a stdlib pulou do Unicode 15 direto para o 17, cobrindo dois releases de uma vez. Se seu app lida com emojis, scripts CJK ou idiomas menos comuns, vale verificar se o comportamento de normalização mudou.
go mod tidy: para módulos com Go 1.27+, o comando agora mescla automaticamente blocos require duplicados. Chega de ter 3 blocos de require espalhados pelo go.mod depois de resolver conflitos de merge.
O que quebraram (e o que removeram)
Toda release do Go remove alguma coisa, e dessa vez a lista é considerável:
- macOS: Go 1.27 exige macOS 13 Ventura ou superior. Se você ainda roda macOS 12, é hora de atualizar.
- bzr: suporte ao Bazaar como VCS para módulos foi removido. Se seu módulo Go ainda está hospedado em um servidor bzr, meus pêsames.
- compress/flate: a implementação interna mudou e o output agora é diferente do Go 1.26. Se seus testes comparam bytes exatos de arquivos comprimidos, vão quebrar. A decompressão continua compatível.
- GODEBUG removidos:
asynctimerchan,gotypesalias, e vários settings de TLS foram permanentemente removidos. Channels criados pelo pacotetimeagora são sempre unbuffered. - Closures renomeadas: a nomenclatura interna de function literals mudou. Testes que verificam nomes de símbolos precisam ser atualizados. E comparar ponteiros de funções ficou menos confiável.
Vale atualizar?
Sem dúvida. Go 1.27 é provavelmente a release mais significativa desde o 1.18 (que trouxe generics). Métodos genéricos sozinhos já justificam a atualização, e o json/v2 vai melhorar a performance de qualquer API REST em Go sem mudar uma linha de código.
Se você mantém projetos Go em produção, teste o RC agora. A maioria das mudanças é retrocompatível, mas o output diferente do compress/flate e os GODEBUGs removidos podem causar surpresas em pipelines de CI muito restritivos.
O go.mod com go 1.27 já habilita as features novas automaticamente, incluindo goroutine labels em tracebacks e a consolidação automática de blocos de require pelo go mod tidy.
Quem diria que um dia o Go seria a linguagem que traz SIMD, criptografia pós-quântica e métodos genéricos na mesma release? Rob Pike provavelmente está olhando pra isso tudo e pensando “era mais simples quando a gente só tinha goroutines e channels”.
A documentação completa está nas release notes oficiais. Se você quer testar antes de atualizar o projeto inteiro, o go install golang.org/dl/go1.27@latest baixa a versão side-by-side sem afetar sua instalação atual.
Fonte de inspiração: Go 1.27 Release Notes e Go 1.27 Interactive Tour (VictoriaMetrics)













