在Go

时间:2016-04-06 17:49:45

标签: go

我正在尝试创建一个可以处理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 {}

2 个答案:

答案 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