← Voltar para o blog

Go 1.24 e o Futuro dos Generics: Novidades 2026

Descubra como generics evoluiram do Go 1.24 ao 1.26: generic type aliases, fim dos core types, self-referencing generics e exemplos praticos para seu codigo.

Generics mudaram Go para sempre quando chegaram no Go 1.18. Mas a historia nao parou ali. De la para ca, cada release trouxe melhorias que tornaram generics mais poderosos, mais simples de usar e mais integrados ao dia a dia do desenvolvedor. Neste artigo, vamos percorrer a evolucao dos generics do Go 1.24 ate o Go 1.26, com exemplos praticos que voce pode aplicar nos seus projetos hoje.

Se voce ainda esta comecando com generics, recomendo antes ler nosso guia pratico de generics e a entrada do glossario sobre generic.

Go 1.24: Generic Type Aliases Finalmente Completos

O Go 1.24, lancado em fevereiro de 2025, trouxe uma das mudancas mais esperadas: generic type aliases completos. Antes, voce podia criar aliases simples com type MinhaString = string, mas nao era possivel parametrizar aliases com tipos genericos. Isso mudou.

Como Funcionam os Generic Type Aliases

Agora voce pode criar aliases que aceitam parametros de tipo:

package collections

// Alias generico para um slice ordenado
type SortedSlice[T constraints.Ordered] = []T

// Alias para um map com chaves string
type StringMap[V any] = map[string]V

Isso e particularmente util quando voce precisa migrar APIs gradualmente. Imagine que voce tem um pacote legado e quer expor tipos novos sem quebrar compatibilidade:

// Pacote antigo exportava OldList
// Agora NewList e o tipo principal, mas OldList continua funcionando
type OldList[T any] = NewList[T]

Weak Pointers e Finalizers Melhorados

O Go 1.24 tambem introduziu o pacote unique com weak pointers – ponteiros que nao impedem o garbage collector de liberar a memoria. Combinados com o novo runtime.AddCleanup (que substitui runtime.SetFinalizer), voce ganha controle mais fino sobre o ciclo de vida de objetos:

package main

import (
    "fmt"
    "runtime"
    "unique"
)

func main() {
    // Handle unico -- se dois valores sao iguais,
    // retorna o mesmo handle (internalizacao)
    h1 := unique.Make("golang")
    h2 := unique.Make("golang")

    fmt.Println(h1 == h2) // true -- mesmo handle

    // AddCleanup substitui SetFinalizer com semantica mais clara
    obj := &MyResource{name: "conexao-db"}
    runtime.AddCleanup(obj, func(name string) {
        fmt.Printf("Recurso %s liberado\n", name)
    }, obj.name)
}

type MyResource struct {
    name string
}

A vantagem do AddCleanup sobre o antigo SetFinalizer e que ele nao impede o garbage collector de coletar o objeto e permite multiplos cleanups no mesmo objeto.

Go 1.25: Adeus Core Types

O Go 1.25 trouxe a mudanca mais significativa para generics desde o Go 1.18: a remocao completa do conceito de “core types”. Se voce ja tentou usar operacoes como range ou channel sends dentro de funcoes genericas e recebeu erros confusos, sabe do que estou falando.

O Problema dos Core Types

No Go 1.18-1.24, o compilador exigia que interfaces usadas como constraints tivessem um “core type” – essencialmente, todos os tipos no type set precisavam ter a mesma estrutura subjacente. Isso gerava restricoes frustrantes:

// Antes do Go 1.25 -- ERRO: nao tem core type
type Iterable interface {
    []int | []string  // tipos diferentes, sem core type
}

func Print[T Iterable](s T) {
    for _, v := range s {  // erro de compilacao!
        fmt.Println(v)
    }
}

A Solucao no Go 1.25+

Com a remocao dos core types, o compilador ficou mais inteligente. Agora ele analisa cada operacao individualmente e verifica se todos os tipos no type set suportam aquela operacao:

// Go 1.25+ -- funciona perfeitamente
type Number interface {
    int | float64 | int64
}

func Sum[T Number](values []T) T {
    var total T
    for _, v := range values {
        total += v
    }
    return total
}

Essa mudanca simplificou a spec da linguagem e abriu portas para patterns mais expressivos com range e operadores dentro de funcoes genericas.

Go 1.26: Self-Referencing Generics

O Go 1.26, lancado em fevereiro de 2026, deu mais um passo importante: tipos genericos agora podem se referenciar na propria lista de parametros de tipo. Isso desbloqueia patterns como:

// Self-referencing -- o tipo T referencia a si mesmo
type Comparable[T interface{ Compare(T) int }] struct {
    Value T
}

// Implementacao concreta
type Score struct {
    Points int
}

func (s Score) Compare(other Score) int {
    return s.Points - other.Points
}

func Max[T interface{ Compare(T) int }](a, b T) T {
    if a.Compare(b) > 0 {
        return a
    }
    return b
}

func main() {
    result := Max(Score{100}, Score{85})
    fmt.Println(result.Points) // 100
}

Esse pattern e essencial para estruturas de dados como arvores binarias de busca, grafos e listas encadeadas genericas – algo que antes exigia workarounds com interfaces vazias ou conversoes de tipo.

Exemplo Pratico: Arvore Binaria Generica

type TreeNode[T interface{ Compare(T) int }] struct {
    Value T
    Left  *TreeNode[T]
    Right *TreeNode[T]
}

func (n *TreeNode[T]) Insert(val T) *TreeNode[T] {
    if n == nil {
        return &TreeNode[T]{Value: val}
    }
    if val.Compare(n.Value) < 0 {
        n.Left = n.Left.Insert(val)
    } else {
        n.Right = n.Right.Insert(val)
    }
    return n
}

Se voce trabalha com structs e ponteiros no dia a dia, esse tipo de codigo generico elimina toneladas de duplicacao.

Usando Generics na Pratica com slices, maps e cmp

Alem das mudancas na linguagem, os pacotes slices, maps e cmp da standard library evoluiram bastante. Aqui estao patterns que todo desenvolvedor Go deveria conhecer em 2026:

package main

import (
    "cmp"
    "fmt"
    "slices"
    "maps"
)

func main() {
    // slices.SortFunc com cmp.Compare
    nums := []int{42, 7, 13, 99, 1}
    slices.SortFunc(nums, cmp.Compare)
    fmt.Println(nums) // [1 7 13 42 99]

    // slices.Contains
    fmt.Println(slices.Contains(nums, 13)) // true

    // maps.Keys e maps.Values (Go 1.24+)
    config := map[string]int{
        "timeout": 30,
        "retries": 3,
        "workers": 8,
    }

    for _, key := range slices.Sorted(maps.Keys(config)) {
        fmt.Printf("%s: %d\n", key, config[key])
    }
}

Esses pacotes eliminam a necessidade de funcoes utilitarias que todo projeto Go costumava ter. Se voce usa map e slice frequentemente, explore essas APIs – elas sao muito mais seguras que loops manuais.

Impacto na Comunidade Brasileira

A pesquisa de desenvolvedores Go de 2025 mostrou que generics ja e uma das features mais adotadas. No Brasil, frameworks como Fiber e bibliotecas como sqlc estao adotando generics em suas APIs. Se voce esta acompanhando o mercado de trabalho Go, saber usar generics de forma idiomatica ja e requisito em muitas vagas.

Para quem trabalha com concorrencia e channels, generics tambem simplificam patterns como fan-out/fan-in e pipelines tipados – temas que cobrimos no artigo sobre padroes de concorrencia.

Desenvolvedores que usam Kotlin ou Python vao notar que os generics do Go seguem uma filosofia diferente: menos magica, mais explicitacao e seguranca de tipos em tempo de compilacao.

Perguntas Frequentes

Generics do Go sao mais lentos que codigo sem generics?

Na maioria dos casos, nao. O compilador Go usa uma combinacao de stenciling (geracao de codigo especializado) e dicionarios para implementar generics. Desde o Go 1.21, as otimizacoes de PGO (Profile-Guided Optimization) tambem beneficiam funcoes genericas. Em benchmarks reais, a diferenca de performance e negligivel.

Preciso reescrever meu codigo para usar generics?

Nao. Generics sao uma ferramenta a mais, nao uma substituicao. Use quando voce tem duplicacao real de logica entre tipos diferentes. Funcoes que operam em um unico tipo concreto nao precisam ser genericas. O principio e: se voce esta copiando e colando codigo mudando apenas o tipo, generics e a solucao certa.

O que muda dos generic type aliases do Go 1.24 para o Go 1.26?

No Go 1.24, generic type aliases foram introduzidos como feature completa. No Go 1.25, a remocao dos core types simplificou como constraints funcionam. No Go 1.26, self-referencing generics permitiram patterns recursivos. Cada versao construiu sobre a anterior sem quebrar compatibilidade.

Quais pacotes da standard library usam generics?

Os principais sao slices, maps, cmp e unique. Alem deles, pacotes como sync (com sync.Map generico no futuro) e sort estao gradualmente adotando generics. Voce pode explorar mais sobre funcoes e interfaces genericas nos nossos glossarios.