Contains em Go para slices: como verificar sem complicação

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

"Cadê o contains?" — a primeira dor de cabeça de quem está começando em Go

\n\n

Imagine: você está programando em Go, tem um slice de strings ["python", "go", "rust", "javascript"] e precisa verificar se a linguagem "go" está presente. Se você veio do Python, Ruby ou JavaScript, automaticamente escreve slice.contains("go") — e leva um erro de compilação vermelho na cara. "Que absurdo é esse?", você pensa. "Qualquer coleção que se preze tem um método contains!"

\n\n

Calma, só calma. No Go, realmente não existe um método contains nativo para slices. E isso não é um bug, é uma feature. Os criadores da linguagem decidiram que uma única função genérica não atenderia a todos os casos (comparação de strings, números, structs) e deixaram a implementação por conta do programador. Parece assustador, mas na prática é simples e elegante. Neste artigo, vamos mostrar como criar um contains para slice em Go, analisar performance, evitar as armadilhas comuns e fornecer soluções prontas.

\n\n

Por que Go não tem contains para slice?

\n

Go é uma linguagem minimalista. Ela não tinha genéricos (até a versão 1.18) nem sobrecarga de métodos. Um slice não é um objeto com métodos, mas uma estrutura de dados: um ponteiro para um array, um comprimento e uma capacidade. Os criadores do Go optaram por tornar a função contains explícita, para que o programador sempre entenda exatamente como a comparação é feita. Isso reduz bugs e torna o código previsível.

\n

Além disso, contains para um slice é sempre uma busca linear (O(n)). Se você espera O(1), está usando a estrutura de dados errada (precisa de um map). O Go não quer mascarar essa complexidade.

\n\n

O contains mais simples para slice em Go (iteração manual)

\n

Vamos escrever um contains para slice de strings. Este é o clássico que você verá em qualquer código de produção:

\n\n
package main\n\nimport "fmt"\n\n// Contains verifica se um elemento existe em um slice de strings\nfunc Contains(slice []string, target string) bool {\n    for _, item := range slice {\n        if item == target {\n            return true\n        }\n    }\n    return false\n}\n\nfunc main() {\n    languages := []string{"python", "go", "rust", "javascript"}\n    fmt.Println(Contains(languages, "go"))       // true\n    fmt.Println(Contains(languages, "csharp"))   // false\n}
\n\n

Simples: percorremos o slice com um loop, comparando cada elemento com o alvo. Se encontrar, retorna true; senão, false. Importante: o operador == funciona para strings, números, booleanos e ponteiros. Para structs ou slices dentro de slices (aninhados), isso não funciona.

\n\n

Contains para números

\n

Para um slice de inteiros, o código é quase idêntico:

\n\n
func ContainsInt(slice []int, target int) bool {\n    for _, v := range slice {\n        if v == target {\n            return true\n        }\n    }\n    return false\n}\n\nfunc main() {\n    numbers := []int{10, 20, 30, 40, 50}\n    fmt.Println(ContainsInt(numbers, 30)) // true\n    fmt.Println(ContainsInt(numbers, 99)) // false\n}
\n\n

Inconveniente? Sim. Mas isso é Go: clareza e simplicidade acima de tudo.

\n\n

Contains universal para slice em Go (genéricos, Go 1.18+)

\n

Com o lançamento do Go 1.18, a linguagem ganhou genéricos. Agora podemos escrever uma única função contains para qualquer tipo que suporte comparação:

\n\n
package main\n\nimport "fmt"\n\n// ContainsGeneric funciona para qualquer tipo comparable\nfunc ContainsGeneric[T comparable](slice []T, target T) bool {\n    for _, item := range slice {\n        if item == target {\n            return true\n        }\n    }\n    return false\n}\n\nfunc main() {\n    strs := []string{"a", "b", "c"}\n    ints := []int{1, 2, 3}\n    floats := []float64{1.1, 2.2, 3.3}\n\n    fmt.Println(ContainsGeneric(strs, "b"))   // true\n    fmt.Println(ContainsGeneric(ints, 5))     // false\n    fmt.Println(ContainsGeneric(floats, 2.2)) // true\n}
\n\n

A restrição comparable significa que o tipo suporta os operadores == e

Blogs

Book Recommendations