我想表达一个可以接受任何 slice 的函数。我认为我可以做到这一点:
func myFunc(list []interface{}) {
for _, i := range list {
...
some_other_fun(i)
...
}
}
其中 some_other_fun(..)
本身采用 interface{}
类型。但是,这不起作用,因为您不能将 []DEFINITE_TYPE
作为 []interface{}
传递。请参阅:https://golang.org/doc/faq#convert_slice_of_interface其中指出 []interface{} 的表示是不同的。这个答案总结了为什么但是关于接口(interface)指针而不是接口(interface) slice ,但原因是一样的:Why can't I assign a *Struct to an *Interface? .
上面 golang.org 链接中提供的建议建议从 DEFINITE_TYPE
slice 重建一个新的接口(interface) slice 。然而,在我想调用这个函数的代码中的任何地方这样做并不实际(这个函数本身意味着只缩写 9 行代码,但这 9 行在我们的代码中出现得相当频繁)。
在我想调用函数的每一种情况下,我都会传递一个 []*DEFINITE_TYPE
,我起初认为它更容易抽象,直到我再次发现 Why can't I assign a *Struct to an *Interface? (也在上面链接)。
此外,每次我想用不同的 DEFINITE_TYPE
调用函数时,因此为 n 个类型实现 n 个示例不会为我节省任何代码行或使我的代码更清晰(相当相反!)。
令人沮丧的是我不能这样做,因为这 9 行代码在我们的代码中是惯用的,而且输入错误很容易引入错误。我真的很想念泛型。真的没有办法吗?!!
最佳答案
在您提供的情况下,您必须将 slice 创建为 interface
的 slice ,例如s := []接口(interface){}{}
。在这一点上,您可以从字面上将任何您想要的类型放入 slice 中(甚至混合类型)。但随后您将不得不进行各种类型断言,一切都变得非常糟糕。
解码器常用的另一种技术是这样的定义:
func myFunc(list interface{})
因为 slice 适合接口(interface)
,所以您确实可以将常规 slice 传递给它。您仍然需要在 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")
}
}
关于go - 接受任何 slice 的 Express 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42987535/