Chegou o Go 1.26 e, olha, a equipe do Go não estava brincando quando falou que essa é a maior release que já fizeram. Não tem uma mudança épica que vai reescrever seu entendimento de programação — mas tem um conjunto de melhorias que, somadas, fazem uma diferença real em produção. Tipo aquele episódio da sua série favorita que não tem o cliffhanger dramático, mas é tão bem executado que você fica satisfeito do mesmo jeito.
Vamos ver o que realmente mudou.
GreenteaGC: De Experimento a Padrão
Se você acompanhou o Go 1.25, já sabe que o GreenteaGC chegou como experimental. Agora, no 1.26, ele virou o padrão. Sem flag, sem opt-in, ele já está rodando no seu código.
O problema do GC anterior era simples de entender: ele tratava todos os objetos de forma igual, varrendo o heap como um grafo gigante e pulando de objeto em objeto pela memória. Em CPUs modernas com vários cores, isso gerava um problema clássico: muito tempo esperando a memória responder, não o processador calcular.
O GreenteaGC foi projetado para workloads modernos — microservices que criam e descartam milhares de objetos pequenos por segundo. O foco dele é em localidade de memória e escalabilidade em multi-core.
Os números que a equipe do Go divulgou:
- 10% a 40% de redução no overhead de GC em programas reais com uso intenso de memória
- +10% adicional em hardware mais novo (Intel Ice Lake, AMD Zen 4 e posteriores), porque o GC agora usa instruções vetoriais para escanear objetos pequenos
// Nenhuma mudança de código necessária.
// Se você estava usando o experimento antes:
// GOEXPERIMENT=greenteagc go run main.go
// Agora é só:
// go run main.go
// Quer desativar por algum motivo? (mas por favor, abra uma issue antes)
// GOEXPERIMENT=nogreenteagc go build .
// Esse opt-out some no Go 1.27, então corra.
Na prática, o que você vai sentir: latência de tail (p99) menor, menos spikes de CPU em load alto, e comportamento mais previsível no Kubernetes quando você tem limites de CPU apertados. É o tipo de melhoria que aparece no seu Datadog sem você ter mudado uma linha de código.
new com Expressão: Finalmente
Essa é pequena, mas se você trabalha com JSON ou Protobuf vai sentir no dia a dia.
Antes, o new só aceitava um tipo. Queria criar um ponteiro para um valor específico? Precisava da clássica função helper que todo projeto Go tem — aquele func ptr[T any](v T) *T que fica copiando de repositório em repositório.
// Antes do Go 1.26
func boolPtr(b bool) *bool { return &b }
func intPtr(i int) *int { return &i }
type Config struct {
MaxRetries *int `json:"max_retries,omitempty"`
Debug *bool `json:"debug,omitempty"`
}
cfg := Config{
MaxRetries: intPtr(3),
Debug: boolPtr(false),
}
// Go 1.26: adeus, funções helpers
type Config struct {
MaxRetries *int `json:"max_retries,omitempty"`
Debug *bool `json:"debug,omitempty"`
}
cfg := Config{
MaxRetries: new(3),
Debug: new(false),
}
Simples. Limpo. Sem boilerplate. O new(expr) aloca uma variável do tipo de expr, inicializa com o valor de expr, e retorna o ponteiro. Funciona com qualquer tipo.
Tipos Genéricos Autorreferenciais
Para quem gosta de estruturas de dados complexas, essa é a mudança mais interessante do ponto de vista da linguagem.
Antes, um tipo genérico não podia se referenciar na sua própria lista de parâmetros de tipo. Isso tornava certas abstrações impossíveis ou extremamente verbosas. Agora dá:
// Go 1.26: tipo genérico que referencia a si mesmo
type Ordered[T Ordered[T]] interface {
Compare(other T) int
}
type TreeNode[T Ordered[T]] struct {
Value T
Left *TreeNode[T]
Right *TreeNode[T]
}
Isso simplifica implementações de árvores binárias de busca, listas encadeadas tipadas, e qualquer estrutura onde você precisa que o tipo saiba sobre si mesmo. Não é uma mudança que vai afetar o código médio, mas quem estava lutando contra as limitações vai agradecer.
Alocações Especializadas por Tamanho
Essa é uma daquelas melhorias invisíveis que aparecem como mágica no benchmark. O compilador agora usa rotas de alocação especializadas para objetos pequenos (abaixo de 512 bytes).
O que acontecia antes: toda alocação passava pela mesma função mallocgc genérica. Funciona, mas não é ótimo quando você está fazendo milhares de alocações por segundo de objetos pequenos.
O que acontece agora: o runtime usa uma jump table para despachar para a função correta baseada no tamanho do objeto. Menos overhead por alocação, melhor uso do cache do processador.
Resultado? Até 30% de redução no custo de alocações pequenas. Em termos práticos, o time do Go estima ~1% de melhoria real em programas com muitas alocações — parece pouco, mas em escala é significativo.
// O compilador também ficou mais esperto com slices.
// Em mais situações, ele consegue alocar o backing store no stack.
// Menos pressão no GC, sem você fazer nada.
func processItems(items []string) []string {
result := make([]string, 0, len(items)) // pode ir pro stack agora em mais casos
for _, item := range items {
result = append(result, transform(item))
}
return result
}
cgo 30% Mais Rápido
Se o seu projeto faz chamadas cgo — seja para bibliotecas C, bindings de sistema, ou criptografia — essa melhoria vai aparecer direto.
O overhead de uma chamada cgo caiu ~30% no baseline. A implementação remove um estado intermediário que o runtime mantinha para goroutines em syscall/cgo. Em vez de encoding o estado "dentro de uma chamada cgo" como estado do processador (P), o runtime agora verifica o status da goroutine diretamente. Menos coordenação, menos contention.
# Benchmark local em Apple M1:
# CgoCall-8: 28.55ns (1.25) → 19.02ns (1.26) = -33%
# CgoCallWithCallback-8: 72.76ns → 57.38ns = -21%
Para quem evitava cgo por causa do overhead, o cenário ficou mais atraente.
crypto/hpke: Criptografia Moderna no stdlib
O Go 1.26 adicionou o pacote crypto/hpke, que implementa Hybrid Public Key Encryption (RFC 9180). Isso inclui suporte a KEMs pós-quânticos como o ML-KEM — ou seja, criptografia que sobrevive a computadores quânticos.
package main
import (
"crypto/hpke"
"fmt"
)
func main() {
suite := hpke.NewSuite(hpke.KEM_X25519_HKDF_SHA256, hpke.KDF_HKDF_SHA256, hpke.AEAD_AES128GCM)
pub, priv, _ := suite.GenerateKeyPair()
sender, _ := suite.NewSender(pub, []byte("info"))
encappedKey, sealer, _ := sender.Setup(nil)
ciphertext, _ := sealer.Seal([]byte("mensagem secreta"), nil)
receiver, _ := suite.NewReceiver(priv, []byte("info"))
opener, _ := receiver.Setup(encappedKey)
plaintext, _ := opener.Open(ciphertext, nil)
fmt.Println(string(plaintext))
}
Menos dependência de bibliotecas terceiras para criptografia moderna. Para quem trabalha com compliance e segurança, isso é relevante.
Experimentos que Vale Ativar Agora
O Go 1.26 vem com alguns experimentos que provavelmente serão padrão no 1.27. Vale ativar no seu ambiente de desenvolvimento e CI:
Goroutine Leak Profile
GOEXPERIMENT=goroutineleakprofile go run main.go
Detecta goroutines que nunca vão desbloquear — aquelas que ficam esperando em channels, mutexes ou variáveis de condição que nenhuma goroutine ativa vai alcançar. Quantas vezes você já debugou um serviço que lentamente acumulava goroutines sem saber por quê? Esse experimento adiciona um endpoint /debug/pprof/goroutineleak e overhead zero quando não está em uso.
runtime/secret: Memória Segura
GOEXPERIMENT=runtimesecret go run main.go
import "runtime/secret"
secret.Do(func() {
key := generateEphemeralKey()
encrypt(data, key)
// Ao sair dessa função, tudo que foi usado aqui é zerado da memória
})
Para quem lida com dados sensíveis (chaves criptográficas, tokens, senhas), essa é uma adição importante. O runtime garante que os dados sejam apagados da memória após o uso — algo que a comunidade pedia desde 2017.
simd/archsimd: SIMD Experimental
GOEXPERIMENT=simd go run main.go
Acesso direto a operações SIMD específicas de arquitetura. Por enquanto só em amd64, mas é o primeiro passo concreto do Go em direção a computação vetorial de alta performance. Se você processa muitos dados numéricos, fique de olho nisso.
Tooling: go fix Ficou Esperto
O go fix foi reconstruído em cima do mesmo framework de análise do go vet. Isso significa que agora ele é mais inteligente, composable, e capaz de fazer modernizações que antes exigiam sed e reza.
# Antes: go fix era limitado e bugado em codebases grandes
# Agora: ele reescreve padrões antigos automaticamente
go fix ./...
Para times que têm codebases grandes e vivem adiando a modernização, esse é o tipo de melhoria que desbloqueia aquele upgrade que todo mundo sabe que precisa fazer mas ninguém quer tocar.
Outra remoção: cmd/doc e go tool doc foram deletados. Use go doc no lugar — aceita os mesmos flags e tem o mesmo comportamento. Sem drama.
O pprof agora também tem a flame graph view como padrão ao usar -http. Se você ainda estava no graph view por inércia, bem-vindo ao presente.
Vale Atualizar Agora?
Go 1.26 requer Go 1.24.6 ou posterior para build. Verifique seu CI/CD antes de atualizar se você builda o toolchain por conta.
O GreenteaGC agora é padrão e o opt-out (GOEXPERIMENT=nogreenteagc) vai ser removido no 1.27. Então se você tem alguma razão para desativá-lo, o momento de investigar e abrir issue é agora.
Para o resto? Atualiza. Você vai ganhar performance de graça, código mais limpo com o novo new, e melhorias de tooling que fazem diferença no dia a dia.
É o tipo de release que não tem headline dramática, mas quando você olha os números no monitoramento duas semanas depois de atualizar, fica claro que valeu.
Ficou curioso para testar alguma das novidades? Me conta nos comentários o que mais chamou sua atenção. E se quiser ver os benchmarks na prática, dá uma olhada no meu repositório de artigos.
Top comments (0)