我正在尝试创建一个可以处理Go中切片上的动作的泛型函数...例如,将任何类型的项追加到同一类型的切片中。这只是一个更复杂的解决方案的通用目的,但整体而言问题归结为这个例子:
package main
type car struct {
make string
color string
}
type submarine struct {
name string
length int
}
func genericAppender(thingList interface{}, thing interface{}) []interface{} {
return append(thingList, thing)
}
func main() {
cars := make([]car, 0, 10)
cars[0] = car{make: "ford", color: "red"}
cars[1] = car{make: "chevy", color: "blue"}
subs := make([]submarine, 0, 10)
subs[0] = submarine{name: "sally", length: 100}
subs[1] = submarine{name: "matilda", length: 200}
newCar := car{make: "bmw", color: "white"}
genericAppender(&cars, newCar)
}
代码操场位于此location
以上错误如下:
prog.go:14: first argument to append must be slice; have interface {}
答案 0 :(得分:3)
在此更改之后,您仍然会收到运行时错误(索引超出范围)但问题是thingList
不是[]interface{}
类型,而是interface{}
所以您可以'附加到它。这是操场上代码的更新版本,它执行类型断言以将其转换为与追加一致的[]interface{}
。实际上,您需要在单独的行上执行此操作并检查错误。
https://play.golang.org/p/YMed0VDZrv
所以在这里放一些代码;
func genericAppender(thingList interface{}, thing interface{}) []interface{} {
return append(thingList.([]interface{}), thing)
}
将解决您面临的基本问题。如上所述,在索引切片时仍然会出现运行时错误。此外,您可以通过制作它来更改参数以避免这种情况;
func genericAppender(thingList []interface{}, thing interface{}) []interface{} {
return append(thingList, thing)
}
这是第二种类型的完整示例; https://play.golang.org/p/dIuW_UG7XY
注意我也纠正了运行时错误。使用带有3个参数的make时,它们按此顺序为类型,长度,容量。这意味着数组的长度为0,因此当您尝试分配索引0和1时,它会导致IndexOutoFRange出现混乱。相反,我删除了中间参数,因此它是make([]interface{}, 10)
,意味着长度最初设置为10,因此您可以分配给这些索引。
答案 1 :(得分:0)
在上面的答案中,如果您执行以下操作,则会抛出错误。这就是最初的问题:
//genericAppender(subs, newCar). // Throws "cannot use subs (type []submarine) as type []interface {} in argument to genericAppender"
诀窍是将您特定类型的切片转换为通用的[]接口{}。
func convertToGeneric(thingList interface{}) []interface{} {
input := reflect.ValueOf(thingList)
length := input.Len()
out := make([]interface{},length)
for i:=0 ;i < length; i++ {
out[i] = input.Index(i).Interface()
}
return out
}
您可以这样调用函数:
genericAppender(convertToGeneric(subs), newCar)
您可以在此处查看修改后的工作代码:https://play.golang.org/p/0_Zmme3c8lT