采用任何切片的Express函数

Jos*_*osh 3 types go

我想表达一个可以采取任何切片的函数.我以为我可以这样做:

func myFunc(list []interface{}) {
  for _, i := range list {
    ...
    some_other_fun(i)
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

some_other_fun(..)本身就是一种interface{}类型.然而,这并不能工作,因为你无法通过[]DEFINITE_TYPE[]interface{}.请参阅:https://golang.org/doc/faq#convert_slice_of_interface,其中指出[]接口{}的表示形式不同.这个答案总结了为什么,但是关于接口指针而不是接口切片,但原因是相同的:为什么我不能将*Struct分配给*接口?.

上面golang.org链接中提供的建议建议从DEFINITE_TYPE切片重建新的接口切片.但是,在我想要调用此函数的代码中到处都是不实际的(这个函数本身只是缩写9行代码,但是这9行在我们的代码中经常出现).

在我想要调用函数的每种情况下,我都会传递一个[]*DEFINITE_TYPE我最初认为更容易抽象的东西,直到我再次发现为什么我不能为*接口分配*Struct?(也在上面链接).

此外,每次我想调用它的功能都是不同的,DEFINITE_TYPE因此实现n个类型的n个示例不会为我节省任何代码行或使我的代码更清晰(恰恰相反!).

令人沮丧的是,我无法做到这一点,因为我们的代码中的9行是惯用的,而错误的类型很容易引入错误.我真的错过了泛型.有没有办法做到这一点?!!

Ray*_*ear 7

在您提供的情况下,您必须创建切片作为interface例如s := []interface{}{}.在这一点上,你可以将任何你想要的类型放入切片中(甚至是混合类型).但是你必须做各种类型的断言,一切都变得非常讨厌.

unmarshalers常用的另一种技术是这样的定义:

func myFunc(list interface{})
Run Code Online (Sandbox Code Playgroud)

因为切片适合interface,所以您确实可以将常规切片传递给它.您仍然需要进行一些验证并输入断言myFunc,但是您将在整个列表类型上执行单个断言,而不必担心可能包含混合类型的列表.

无论哪种方式,由于是静态类型语言,您最终必须知道通过断言传递的类型.这就是事情的方式.在你的情况下,我可能会使用上面的func签名,然后使用类型开关来处理不同的情况.请参阅此文档https://newfivefour.com/golang-interface-type-assertions-switch.html

所以,像这样:

func myFunc(list interface{}) {
    switch v := list.(type) {
        case []string:
            // do string thing
        case []int32, []int64:
            // do int thing
        case []SomeCustomType:
            // do SomeCustomType thing
        default:
            fmt.Println("unknown")
    }
}
Run Code Online (Sandbox Code Playgroud)


And*_*eig 3

也许最好的办法是定义一个接口来封装需要myFunc对切片执行的操作(即,在您的示例中,获取第 n 个元素)。然后函数的参数是接口类型,并且您为要传递给函数的每种类型定义接口方法。

您也可以使用reflect包来完成此操作,但这可能不是一个好主意,因为如果您传递除切片(或数组或字符串)之外的其他内容,它会出现恐慌。

func myFunc(list interface{}) {
    listVal := reflect.ValueOf(list)
    for i := 0; i < listVal.Len(); i++ {
        //...
        some_other_fun(listVal.Index(i).Interface())
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

请参阅https://play.golang.org/p/TyzT3lBEjB