3

假设我想在 Go 中为 Slices制作等效的JavaScript函数。Array.splice我有以下代码:

func splice(slice []int, index, amount int, elements ...int) []int {
    newslice := make([]int, 0)
    for i := 0; i < index; i++ {
        newslice = append(newslice, slice[i])
    }
    for i := index + amount; i < len(slice); i++ {
        newslice = append(newslice, slice[i])
    }
    for _, el := range elements {
        newslice = append(newslice, el)
    }
    return newslice
}

此示例将有效,但仅适用于 type 的参数int。我想让它成为通用的,并且我知道我应该给可变参数elements提供 type interface{},但是如何从函数内部创建一个具有该接口类型的新切片?

换句话说,如何根据函数第一行中的参数类型动态指定切片的类型,在哪里newslice创建?

4

2 回答 2

6

而不是在 Go 中模拟 JavaScript(为什么???)我想建议从 SliceTricks 的构建块中编写类似的所需操作

他们是:

  • 完全不知道类型(免费考虑“泛型”)。
  • 与在[]interface{}.
于 2012-12-06T22:45:17.273 回答
5

使用反射

如果你真的想做通用的东西,反射是最终的答案。有关您的问题的详细信息,请参阅反射包中的MakeSlice 文档

您只需要检索传入切片的类型(使用TypeOf(...))并MakeSlice正确应用。

使用反射创建切片的示例:

y := []int{1,2,3}
t := reflect.TypeOf(y)

slice := reflect.MakeSlice(t, 0, 10)
slice = reflect.Append(slice, reflect.ValueOf(2))

fmt.Println(slice.Interface())

在这里运行它

使用[]interface{}

另一种使用方法是[]interface{},它可以存储任何值,但可能会导致运行时恐慌,因为您完全忽略了编译器类型检查(这是一件坏事)。

是一个用于[]interface{} 存储任意值的示例。有了这个,您不需要知道拼接实现中的类型,您只需拼接并[]interface{}用于新切片。

这种方法有一个缺点,您不能[]interface{}轻松地将某些切片转换为。您必须手动复制它,如之前的帖子中所述。

结论

无论您使用哪个版本,如果不知道类型并手动将其转换回来,您将永远无法恢复类型安全。Go 中没有这样的东西可以为你做到这一点。这意味着,您将在代码中使用类似的内容来重新获得类型安全:

x := []int{1,2,3,4}
y := splice(x, ...)
yn := []int(y)
于 2012-12-07T00:49:59.273 回答