Concatenação de slices em Go: do iniciante ao profissional em 2025
Slices em Go são arrays dinâmicos que são o coração da maioria das aplicações Go. Mais cedo ou mais tarde, todo desenvolvedor enfrenta a tarefa: "Como combinar dois slices em um?". Parece uma operação trivial, mas, como muitas coisas em Go, ela tem suas armadilhas e nuances de desempenho.
No Stack Overflow, esta pergunta acumulou milhares de visualizações, e não é à toa: uma concatenação não otimizada pode levar a alocações de memória desnecessárias e redução na velocidade da aplicação. Neste artigo, vamos analisar todas as maneiras legais de unir dois slices, desde o clássico append até as novidades da biblioteca padrão de 2025, e descobrir qual método escolher dependendo da situação.
Por que a simples adição não funciona?
Ao contrário do Python (list1 + list2) ou JavaScript (arr1.concat(arr2)), Go não suporta o operador + para slices. Isso foi feito intencionalmente: Go é uma linguagem que exige explicitude. Cada operação com slices deve ser transparente, especialmente no que diz respeito ao gerenciamento de memória.
Vamos direto ao ponto. Aqui está a maneira mais simples e comum:
package main
import "fmt"
func main() { slice1 := []int{1, 2, 3} slice2 := []int{4, 5, 6}
// Método #1: append com descompactação result := append(slice1, slice2...) fmt.Println(result) // [1 2 3 4 5 6]}Este código funciona, mas tem uma nuance. Se slice1 tiver capacidade (cap) suficiente, o append o modificará, em vez de criar um novo slice. Isso pode levar a efeitos colaterais inesperados se você não esperava a mutação do slice original.
Concatenação segura com make + copy
Se você precisa de independência garantida do resultado em relação aos slices originais, use a combinação de make e copy. Este é o "padrão ouro" para criar um novo slice sem o risco de alterar o original.
func concatSlices[T any](a, b []T) []T { result := make([]T, len(a)+len(b)) copy(result, a) copy(result[len(a):], b) return result}
// Uso:combined := concatSlices(slice1, slice2)Por que isso é bom?
- Previsibilidade: Você sempre cria um novo slice. Os dados originais permanecem intactos.
- Controle: Você aloca memória explicitamente uma vez, em vez de depender da lógica interna do
append. - Genéricos (Go 1.18+): A função funciona com qualquer tipo de dado.
Abordagem moderna: slices.Concat (Go 1.22+)
A partir da versão Go 1.22 (que em 2025 já se tornou padrão há muito tempo), a função Concat foi adicionada ao pacote golang.org/x/exp/slices. No Go 1.22, ela foi movida para a biblioteca padrão.
Esta é a maneira oficial e recomendada de concatenação, que combina a segurança do copy com a concisão do append.
import "slices"
func main() { a := []string{"Go", "Python", "Rust"} b := []string{"JavaScript", "TypeScript"}
combined := slices.Concat(a, b) // combined = ["Go", "Python", "Rust", "JavaScript", "TypeScript"]}Vantagens do slices.Concat:
- Legibilidade: O nome fala por si. O código se torna declarativo.
- Otimização: Internamente, usa alocação eficiente e
copy. - Flexibilidade: Você pode passar qualquer número de slices:
slices.Concat(s1, s2, s3, s4).
Se você está escrevendo código em Go 1.22+ (e em 2025 isso é mainstream), use slices.Concat sem medo. É a melhor escolha para 90% das tarefas.
Quando o append ainda é necessário?
Clássico