小能豆

Why do functions in the slices package define a type parameter for the slice argument?

go

Why is the BinarySearch function in the slices package defined like this:

func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool)

And not like this:

func BinarySearch[E cmp.Ordered](x []E, target E) (int, bool)

I tried to write code that works with the first one and does not compile with the second definition. But I’m new to go and I have no idea.


阅读 80

收藏
2023-12-18

共1个答案

小能豆

The notation S ~[]E is a type parameter constraint introduced in the generics proposal for Go (Generics in Go: https://golang.org/design/43651-type-parameters). It constrains the type S to be a slice ([]E).

In the first function signature you provided

func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool)
  • S is a type parameter that represents a slice (~[]E).
  • E is another type parameter representing an element type that must implement the cmp.Ordered interface.

In this case, the function is designed to work with slices of any type ([]E) as long as the element type (E) implements the cmp.Ordered interface. The use of S ~[]E ensures that S is a slice type, and the constraints on E ensure that the element type is ordered.

Now, if you were to define the function as:

func BinarySearch[E cmp.Ordered](x []E, target E) (int, bool)

It would still work, but it would be limited to slices, and the type parameter E would apply only to the element type. The first version with S provides a more generic interface that explicitly communicates the expectation that x is a slice.

Here’s a simple example of how you can use the BinarySearch function with the first signature:

package main

import (
    "fmt"
    "sort"
)

func main() {
    ints := []int{1, 2, 3, 4, 5}
    index, found := BinarySearch(ints, 3)
    fmt.Printf("Index: %d, Found: %v\n", index, found)
}

func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool) {
    index := sort.Search(len(x), func(i int) bool {
        return x[i] >= target
    })

    if index < len(x) && x[index] == target {
        return index, true
    }

    return index, false
}

In this example, ints is a slice of integers, and the BinarySearch function is used to find the index of the target value (3). The use of type parameters allows you to create a flexible and reusable function that works with slices of any ordered type.

2023-12-18