有没有办法编写通用代码来查找 Go 中切片是否包含特定元素?

arm*_*ong 5 contains go slice

我想知道是否有一种通用的方法来编写代码来判断切片是否包含元素,我发现它经常很有用,因为有很多逻辑来首先判断特定元素是否已经在切片中,然后决定要做什么接下来做。但似乎没有一个内置的方法(看在上帝的份上,为什么?)

我尝试interface{}这样做:

func sliceContains(slice []interface{}, elem interface{}) bool {
    for _, item := range slice {
       if item == elem {
          return true
       }
    }
    return false
}
Run Code Online (Sandbox Code Playgroud)

我认为interface{}这有点像ObjectJava,但显然我错了。每次遇到新的切片结构时我都应该写这个吗?没有通用的方法来做到这一点吗?

Not*_*fer 4

您可以使用 来完成此操作reflect,但它会比非通用等效函数慢得多:

func Contains(slice, elem interface{}) bool {

    sv := reflect.ValueOf(slice)

    // Check that slice is actually a slice/array. 
    // you might want to return an error here
    if sv.Kind() != reflect.Slice && sv.Kind() != reflect.Array {
        return false
    }

    // iterate the slice
    for i := 0; i < sv.Len(); i++ {

        // compare elem to the current slice element
        if elem == sv.Index(i).Interface() {
            return true
        }
    }

    // nothing found
    return false


}

func main(){
    si := []int {3, 4, 5, 10, 11}
    ss := []string {"hello", "world", "foo", "bar"}

    fmt.Println(Contains(si, 3))
    fmt.Println(Contains(si, 100))
    fmt.Println(Contains(ss, "hello"))
    fmt.Println(Contains(ss, "baz"))

}
Run Code Online (Sandbox Code Playgroud)

慢了多少?大约慢 x50-x60:针对以下形式的非泛型函数进行基准测试:

func ContainsNonGeneic(slice []int, elem int) bool {
    for _, i := range slice {
        if i == elem {
            return true
        }
    }
    return false
}
Run Code Online (Sandbox Code Playgroud)

我越来越:

  • 通用的:N=100000, running time: 73.023214ms 730.23214 ns/op
  • 非通用:N=100000, running time: 1.315262ms 13.15262 ns/op