Contains en Go pour les slices : comment vérifier sans perdre la tête

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

« Mais où est contains ? » — la première galère du débutant en Go

\n\n

Imaginez : vous codez en Go, vous avez un slice de chaînes ["python", "go", "rust", "javascript"], et vous devez vérifier si le langage "go" s'y trouve. Si vous venez de Python, Ruby ou JavaScript, vous écrivez instinctivement slice.contains("go") — et vous obtenez une erreur de compilation rouge. « C'est quoi ce délire ? » pensez-vous. « Dans toute collection qui se respecte, il y a une méthode contains ! »

\n\n

Du calme, respirez. En Go, il n'existe pas de méthode contains intégrée pour les slices. Et ce n'est pas un bug, c'est une feature. Les créateurs du langage ont estimé qu'une seule fonction universelle ne couvrirait pas tous les cas (comparaison de chaînes, nombres, structures) et ont laissé l'implémentation au développeur. Ça semble effrayant, mais en réalité c'est simple et élégant. Dans cet article, nous allons voir comment écrire un contains pour slice en Go, analyser les performances, les pièges classiques et vous donner des solutions prêtes à l'emploi.

\n\n

Pourquoi Go n'a-t-il pas de contains pour les slices ?

\n

Go est un langage minimaliste. Il n'avait pas de génériques (avant la version 1.18) ni de surcharge de méthodes. Un slice n'est pas un objet avec des méthodes, mais une structure de données : un pointeur vers un tableau, une longueur et une capacité. Les développeurs de Go ont choisi que la fonction contains soit explicite, afin que le programmeur comprenne toujours comment la comparaison est effectuée. Cela réduit les bugs et rend le code prévisible.

\n

De plus, contains pour un slice est toujours une recherche linéaire (O(n)). Si vous attendez du O(1), vous utilisez la mauvaise structure (il vous faut une map). Go ne veut pas masquer cette complexité.

\n\n

Le contains le plus simple pour un slice en Go (parcours manuel)

\n

Écrivons un contains pour un slice de chaînes. C'est un classique que vous verrez dans tout code de production :

\n\n
package main\n\nimport "fmt"\n\n// Contains vérifie si un élément est présent dans un slice de chaînes\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

C'est simple : on parcourt le slice avec une boucle, on compare chaque élément à la cible. Si on trouve une correspondance — true, sinon false. Important : l'opérateur == fonctionne pour les chaînes, les nombres, les booléens et les pointeurs. Pour les structures ou les slices imbriqués, ça ne marchera pas.

\n\n

Contains pour les nombres

\n

Pour un slice d'entiers, le code est presque identique :

\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

Pas pratique ? Oui. Mais c'est Go — la clarté et la simplicité avant tout.

\n\n

Contains universel pour slice en Go (génériques, Go 1.18+)

\n

Avec la sortie de Go 1.18, le langage a introduit les génériques. Vous pouvez désormais écrire une seule fonction contains pour tout type comparable :

\n\n
package main\n\nimport "fmt"\n\n// ContainsGeneric fonctionne pour tout type 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

La contrainte comparable signifie que le type supporte les opérateurs == et

Blogs

Book Recommendations