generics - 复制 slice 的通用方法

标签 generics go

我需要复制 slice (和底层数组的一部分),这样调用者就不会改变数组的原始元素。我想我可以编写一个函数来为特定类型的数组执行此操作:

func duplicateSliceOfSomeType(sliceOfSomeType []SomeType) []SomeType {
    dulicate := make([]SomeType, len(sliceOfSomeType))
    copy(duplicate, sliceOfSomeType)
    return duplicate
}

但是有没有一种方法可以通用地创建相同的方法,也许不需要泛型?

func duplicateSlice(slice []?) []?{
    duplicate := make([]?, len(slice))
    copy(duplicate, slice)
    return duplicate
}

最佳答案

你可以写一个简单的语句来制作一个 slice 的浅拷贝,

b := append([]T(nil), a...)

相当于,

b := make([]T, len(a))
copy(b, a)

例如,

package main

import "fmt"

type T int

func main() {
    a := []T{4, 2}

    b := append([]T(nil), a...)

    fmt.Println(&a[0], a, &b[0], b)
    b[0] = 9
    fmt.Println(&a[0], a, &b[0], b)
}

输出:

0x10328000 [4 2] 0x10328020 [4 2]
0x10328000 [4 2] 0x10328020 [9 2]

附录:

Common difficulties with reflection

If people are new to Go, they shouldn't be using reflection at all.

-rob

Reflection is subtle even for experts. It exposes details whose understanding depends on knowing pretty fundamental things about how the language works and, to a lesser extent, how it is implemented. It can be bewildering even for experienced Go programmers; for newly minted Gophers there are much more important, simpler things to learn first. Those who learn reflection too early confuse themselves cloud their understanding of those fundamentals. Best to keep it at arm's length until the rest of the picture is clear.

-rob

也就是说,

package main

import (
    "fmt"
    "reflect"
)

func CopySlice(s interface{}) interface{} {
    t, v := reflect.TypeOf(s), reflect.ValueOf(s)
    c := reflect.MakeSlice(t, v.Len(), v.Len())
    reflect.Copy(c, v)
    return c.Interface()
}

type T int

func main() {

    {
        // append
        a := []T{4, 2}
        b := append([]T(nil), a...)
        fmt.Println(&a[0], a, &b[0], b)
        b[0] = 9
        fmt.Println(&a[0], a, &b[0], b)
    }

    {
        // make and copy
        a := []T{4, 2}
        b := make([]T, len(a))
        copy(b, a)
        fmt.Println(&a[0], a, &b[0], b)
        b[0] = 9
        fmt.Println(&a[0], a, &b[0], b)
    }

    {
        // reflection
        a := []T{4, 2}
        b := CopySlice(a).([]T)
        fmt.Println(&a[0], a, &b[0], b)
        b[0] = 9
        fmt.Println(&a[0], a, &b[0], b)
    }

}

输出:

0xc20800a200 [4 2] 0xc20800a210 [4 2]
0xc20800a200 [4 2] 0xc20800a210 [9 2]
0xc20800a290 [4 2] 0xc20800a2a0 [4 2]
0xc20800a290 [4 2] 0xc20800a2a0 [9 2]
0xc20800a310 [4 2] 0xc20800a320 [4 2]
0xc20800a310 [4 2] 0xc20800a320 [9 2]

关于generics - 复制 slice 的通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26433156/

相关文章:

java - 如何将实现特定接口(interface)的任何类作为参数传递并使用其方法?

python - 不同语言编写的 ZeroMQ 套接字的兼容性

go - 如何在 CLI 中列出某种类型满足的接口(interface)?

C# 泛型和使用类型化方法的非泛型版本

generics - 我们可以在 Kotlin 中使用中缀泛型方法吗?

Java 泛型 : Illegal forward reference

generics - 序言中的 "Generic programming"

json:无法将数字 5088060241 解码为 int 类型的结构

json - 如何解码以下 JSON?

go - 为什么没有渲染模板?