复制Go切片的通用方法?

初学者进入此处的程序员。 我需要复制切片(以及基础数组的一部分),以便调用者不会更改数组的原始元素。 我想我可以编写一个函数来对特定类型的数组执行此操作:</ p>

  funcplicateSliceOfSomeType(sliceOfSomeType [] SomeType)[] SomeType {
dulicate:= make([ ] SomeType,len(sliceOfSomeType)
复制(duplicate,sliceOfSomeType)
返回重复项
}
</ code> </ pre>

但是有一种方法可以创建相同的方法 一般而言,也许没有泛型?</ p>

  funcplicateSlice(slice []?)[]?{
重复:= make([] ?, len(slice))
复制(重复,切片)
返回重复
}
</ code> </ pre>
</ div>

展开原文

原文

Beginner Go programmer here. I have a need to duplicate slices (and part of the underlying array) so a caller won't mutate the original elements of an array. I think I can write a function to do this for arrays of specific types:

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

But is there a way to create the same method generically, perhaps without generics?

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

2个回答

You could write one simple statement to make a shallow copy of a slice,

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

Which is equivalent to,

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

For example,

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)
}

Output:

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

ADDENDUM:

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

That said,

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)
    }

}

Output:

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]
drnl10253
drnl10253 [] T {}是具有分配的后备数组的空片,而不是nil片。 因此,[] T(nil)更有效。
2 年多之前 回复
drghhp8706
drghhp8706 对于更短的使用b:= append([] T {},a ...)
大约 3 年之前 回复
dongshiqin1352
dongshiqin1352 他们是一样的。 对于:= make([] T,256),BenchmarkAppend 7026 ns / op。 BenchmarkMakeCopy 7054 ns / op。
接近 6 年之前 回复
drzb7969753
drzb7969753 在nil slice的追加部分将转换为make和copy。 请参阅我的修订答案。
接近 6 年之前 回复
duannao3819
duannao3819 追加方法是否与make / copy方法一样有效?
接近 6 年之前 回复
dongsou4301
dongsou4301 因此,实质上,您是将a的元素附加到分配给b的新数组的新的空切片中,对吗?
接近 6 年之前 回复



您可以使用 reflect </ code>包(特别是 reflect.Copy)对任何类型的副本进行复制。 </ code>: http://golang.org/pkg/reflect/#Copy < / p>
</ div>

展开原文

原文

You can do a copy on any type by using the reflect package, specifically reflect.Copy: http://golang.org/pkg/reflect/#Copy

dreamice2013
dreamice2013 我希望看到一个具体的例子。
接近 6 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问