func indexOf[T comparable](s []T, x T) (int, error) {
for i, v := range s {
// v and x are type T, which has the comparable
// constraint, so we can use == here.
if v == x {
return i, nil }
}
return0, errors.New("not found")
}
// Signed is a constraint that permits any signed integer type.
// If future releases of Go add new predeclared signed integer types,
// this constraint will be modified to include them.
type Signed interface {
~int | ~int8 | ~int16 | ~int32 | ~int64}
// Unsigned is a constraint that permits any unsigned integer type.
// If future releases of Go add new predeclared unsigned integer types,
// this constraint will be modified to include them.
type Unsigned interface {
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr}
// Integer is a constraint that permits any integer type.
// If future releases of Go add new predeclared integer types,
// this constraint will be modified to include them.
type Integer interface {
Signed | Unsigned
}
func indexOfInteger[T constraints.Integer](s []T, x T) (int, error) {
for i, v := range s {
// v and x are type T, which has the comparable
// constraint, so we can use == here.
if v == x {
return i, nil }
}
return0, errors.New("not found")
}
func indexOfFloat[T constraints.Float](s []T, x T) (int, error) {
for i, v := range s {
// v and x are type T, which has the comparable
// constraint, so we can use == here.
if v == x {
return i, nil }
}
return0, errors.New("not found")
}
package main
import (
"errors""fmt""golang.org/x/exp/slices")
func indexOf[T comparable](s []T, x T) (int, error) {
for i, v := range s {
// v and x are type T, which has the comparable
// constraint, so we can use == here.
if v == x {
return i, nil }
}
return0, errors.New("not found")
}
funcmain() {
i, err := indexOf([]string{"apple", "banana", "pear"}, "banana")
fmt.Println(i, err)
i, err = indexOf([]int{1, 2, 3}, 3)
fmt.Println(i, err)
fmt.Println(slices.Index([]string{"apple", "banana", "pear"}, "banana"))
}
// Index returns the index of the first occurrence of v in s,
// or -1 if not present.
func Index[E comparable](s []E, v E) int {
for i, vs := range s {
if v == vs {
return i
}
}
return -1}
// BinarySearch searches for target in a sorted slice and returns the smallest
// index at which target is found. If the target is not found, the index at
// which it could be inserted into the slice is returned; therefore, if the
// intention is to find target itself a separate check for equality with the
// element at the returned index is required.
func BinarySearch[Elem constraints.Ordered](x []Elem, target Elem) int {
returnsearch(len(x), func(i int) bool { return x[i] >= target })
}
funcsearch(n int, f func(int) bool) int {
// Define f(-1) == false and f(n) == true.
// Invariant: f(i-1) == false, f(j) == true.
i, j := 0, n
for i < j {
h := int(uint(i+j) >> 1) // avoid overflow when computing h
// i ≤ h < j
if !f(h) {
i = h + 1// preserves f(i-1) == false
} else {
j = h // preserves f(j) == true
}
}
// i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i.
return i
}
// ToString convert any type to string
funcToString(value interface{}) string {
if v, ok := value.(*string); ok {
return *v
}
return fmt.Sprintf("%v", value)
}
// ToBool convert any type to boolean
funcToBool(value interface{}) bool {
switch value := value.(type) {
casebool:
return value
caseint:
if value != 0 {
returntrue }
returnfalse }
returnfalse}