Represent and transform data safely
Find an Element in a Go Slice with `slices.Index` or a Loop
Find the first matching index in a Go slice, check membership, or search by predicate with standard-library helpers and simple loops.

If you need an element’s position in a slice, use slices.Index(slice, value). It returns the first index where the value occurs, or -1 if it is absent. If you only need a yes/no answer, use slices.Contains instead. For a condition such as “the first value greater than 10,” a short loop makes the predicate and its result explicit.
The standard-library slices.Contains is available in Go 1.21 and later. If the standard-library helper you need is unavailable in your toolchain, or the search needs custom logic, use a loop.
Get the first equal element with slices.Index
This complete example shows a present value, an absent value, a value that appears twice, and two predicate searches:
package main
import (
"fmt"
"slices"
)
func main() {
numbers := []int{7, 4, 7, 12}
fmt.Println("first 7:", slices.Index(numbers, 7))
fmt.Println("12:", slices.Index(numbers, 12))
fmt.Println("9:", slices.Index(numbers, 9))
fmt.Println("contains 7:", slices.Contains(numbers, 7))
fmt.Println("contains 9:", slices.Contains(numbers, 9))
fmt.Println("first > 10:", firstIndexWhere(numbers, func(n int) bool {
return n > 10
}))
fmt.Println("first < 0:", firstIndexWhere(numbers, func(n int) bool {
return n < 0
}))
}
func firstIndexWhere(numbers []int, match func(int) bool) int {
for i, n := range numbers {
if match(n) {
return i
}
}
return -1
}
The results are:
first 7: 0
12: 3
9: -1
contains 7: true
contains 9: false
first > 10: 3
first < 0: -1
The second 7 is at index 2, but Index returns 0 because it finds the first occurrence. The Go team’s implementation example shows how: it visits indexes in order, compares each element with ==, and returns immediately on a match. Only after reaching the end does it return -1. Check for -1 before using the result to access the slice; -1 is a search result, not an element’s position.
Index and Contains take values of a comparable element type. If equality is not the test you want, describe the match with a predicate instead. For more on comparable constraints when writing your own generic helper, see Go Generics: How to Write Type Parameters, Constraints, and Generic Interfaces.
Choose a boolean or a predicate when that is the real question
Use slices.Contains(numbers, 7) when the caller does not need an index. It reports whether the value is present, so there is no -1 result to interpret. The standard-library documentation also provides ContainsFunc when the question is whether any element satisfies a predicate; it stops when one does.
When you need the position of a predicate match, firstIndexWhere returns at the first successful call to match. In the example, n > 10 first succeeds at index 3. The n < 0 predicate never succeeds, so the loop reaches return -1. This differs from looking for a particular value: the caller defines what counts as a match. If several elements qualify, stopping immediately preserves the first matching index.
For an unsorted slice, do not substitute slices.BinarySearch just because its name suggests a faster lookup. Its standard-library contract requires increasing sort order and returns both a position and a found boolean. When the value is absent, that position is where it would belong, not evidence that it exists.
Write a loop for an older toolchain or custom logic
When a standard-library search helper is unavailable, an index loop performs the equality search without a slices import:
func firstIndex(numbers []int, wanted int) int {
for i, n := range numbers {
if n == wanted {
return i
}
}
return -1
}
For []int{7, 4, 7, 12}, firstIndex(numbers, 7) returns 0 and firstIndex(numbers, 9) returns -1. Return as soon as the match is found: continuing through the slice would no longer implement a first-index search. This type-specific function also keeps the equality rule visible. If the rule instead depends on a condition, use the predicate loop above or put that condition directly in the loop.





Comments
No comments yet.