How to Use `slices.Contains` in Go: A Complete Guide to Generic Slice Search
Use slices.Contains from the standard library slices package (Go 1.21+) to check if a comparable value exists in a slice, replacing manual loops with a clean, generic function call.
The slices.Contains function is a modern Go idiom recommended by the JetBrains/go-modern-guidelines repository for searching slice contents. Introduced in Go 1.21 as part of the standard library, this generic helper eliminates boilerplate code when checking for element presence.
Understanding the slices.Contains Function Signature
The function uses Go generics to work with any slice type whose elements are comparable. According to the repository's [internal/guidelines/guidelines.json](https://github.com/JetBrains/go-modern-guidelines/blob/main/internal/guidelines/guidelines.json#L739) (line 739, guideline ID slices_contains), the signature is:
func Contains[S ~[]E, E comparable](s S, v E) bool
- S represents any slice type with underlying type
[]E - E is the element type constrained by
comparable, meaning values can be compared with==and!= - The function returns
trueifvexists ins,falseotherwise
This design allows slices.Contains to work with custom slice types while enforcing compile-time safety through the comparable constraint.
Installation and Import Requirements
Your import path depends on your Go version.
- Go 1.21 or newer: Import
"slices"from the standard library - Go 1.20 or older: Import
"golang.org/x/exp/slices"from the experimental module
The repository's [README.md](https://github.com/JetBrains/go-modern-guidelines/blob/main/README.md#L7) explicitly lists slices.Contains as a modern idiom that code agents should generate, emphasizing its status as a standard replacement for manual iteration.
Practical Code Examples
Checking Integer Slices
Replace manual loops when checking for numeric presence:
package main
import (
"fmt"
"slices"
)
func main() {
numbers := []int{1, 2, 3, 4, 5}
if slices.Contains(numbers, 3) {
fmt.Println("3 is present")
} else {
fmt.Println("3 is not present")
}
}
Searching String Slices
Work with string collections without writing for loops:
package main
import (
"fmt"
"slices"
)
func main() {
fruits := []string{"apple", "banana", "cherry"}
fmt.Println(slices.Contains(fruits, "banana")) // true
fmt.Println(slices.Contains(fruits, "grape")) // false
}
Working with Custom Comparable Structs
Use slices.Contains with user-defined types as long as all fields are comparable (no slices, maps, or functions):
package main
import (
"fmt"
"slices"
)
type Point struct {
X, Y int
} // Point is comparable because it contains only comparable fields
func main() {
pts := []Point{{1, 2}, {3, 4}, {5, 6}}
target := Point{3, 4}
fmt.Println(slices.Contains(pts, target)) // true
}
Backward Compatibility for Older Go Versions
If you're maintaining code on Go versions prior to 1.21, use the experimental package with identical API:
package main
import (
"fmt"
"golang.org/x/exp/slices"
)
func main() {
data := []byte{'a', 'b', 'c'}
fmt.Println(slices.Contains(data, byte('b'))) // true
}
Why slices.Contains Replaces Manual Loops
The JetBrains guidelines recommend slices.Contains because it expresses intent more clearly than a for loop that breaks early on match. The generic implementation in the standard library provides:
- Type safety: The
comparableconstraint catches non-comparable types at compile time - Performance: Optimized implementation that short-circuits on first match
- Readability: One-line check versus three-to-five lines of iteration boilerplate
Summary
- Import
"slices"for Go 1.21+, or"golang.org/x/exp/slices"for older versions - Apply to any slice of comparable types (ints, strings, structs without slice/map fields)
- Reference the guideline in
internal/guidelines/guidelines.jsonfor authoritative recommendations - Replace manual
forloops withslices.Contains(s, v)for clearer presence checks
Frequently Asked Questions
What Go version do I need for slices.Contains?
You need Go 1.21 or later to use slices.Contains from the standard library. For Go 1.20 and earlier, install golang.org/x/exp/slices which provides the same function signature and behavior.
Can I use slices.Contains with slices of structs?
Yes, if the struct is comparable. A struct is comparable only if all its fields are comparable types (no slices, maps, or functions). The compiler enforces this constraint through the E comparable type parameter.
What's the difference between the standard library and x/exp versions?
There is no API difference—the golang.org/x/exp/slices package served as the experimental proving ground before standard library inclusion. The standard library version (Go 1.21+) offers long-term stability guarantees, while the experimental package may receive breaking changes.
Does slices.Contains work with custom slice types?
Yes. The signature S ~[]E uses a type approximation, meaning slices.Contains accepts both raw slices ([]int) and defined types based on slices (type Ints []int). The function handles type conversion automatically while preserving the specific slice type.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →