# How to Use `slices.Contains` in Go: A Complete Guide to Generic Slice Search

> Learn to use Go's slices.Contains for efficient, generic slice searching. Replace manual loops with this simple, powerful standard library function. Find elements fast.

- Repository: [JetBrains/go-modern-guidelines](https://github.com/jetbrains/go-modern-guidelines)
- Tags: how-to-guide
- Published: 2026-08-29

---

**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](https://github.com/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)](https://github.com/JetBrains/go-modern-guidelines/blob/main/internal/guidelines/guidelines.json#L739) (line 739, guideline ID `slices_contains`), the signature is:

```go
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 `true` if `v` exists in `s`, `false` otherwise

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)](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:

```go
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:

```go
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):

```go
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:

```go
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 `comparable` constraint 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.json`](https://github.com/JetBrains/go-modern-guidelines/blob/main/internal/guidelines/guidelines.json) for authoritative recommendations
- **Replace** manual `for` loops with `slices.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.