Concisely deep copy a slice?

前端 未结 3 886
粉色の甜心
粉色の甜心 2020-12-17 17:11

In Go, what\'s a concise/well-performing way to deep copy a slice? I need to copy the slice to a new backing array, because the other array is owned by something else and ma

3条回答
  •  南方客
    南方客 (楼主)
    2020-12-17 17:52

    slicecopy := append([]T(nil), slice...)
    

    For example,

    package main
    
    import "fmt"
    
    func main() {
        type T int
        slice := make([]T, 8)
        for i := range slice {
            slice[i] = T(i)
        }
        fmt.Println(len(slice), cap(slice), &slice[0], slice)
        slicecopy := append([]T(nil), slice...)
        fmt.Println(len(slicecopy), cap(slicecopy), &slicecopy[0], slicecopy)
    }
    

    Output:

    8 8 0x10322160 [0 1 2 3 4 5 6 7]
    8 8 0x103221a0 [0 1 2 3 4 5 6 7]
    

    References:

    Arrays, slices (and strings): The mechanics of 'append'

    // Make a copy of a slice (of int).
    slice3 := append([]int(nil), slice...)
    fmt.Println("Copy a slice:", slice3)
    

    Benchmarks:

    package main
    
    import "testing"
    
    var result []T
    
    const size = 1000
    
    type T int
    
    func BenchmarkCopy(b *testing.B) {
        orig := make([]T, size)
        for n := 0; n < b.N; n++ {
            cpy := make([]T, len(orig))
            copy(cpy, orig)
            orig = cpy
        }
        result = orig
    }
    
    func BenchmarkAppend(b *testing.B) {
        orig := make([]T, size)
        for n := 0; n < b.N; n++ {
            cpy := append([]T{}, orig...)
            orig = cpy
        }
        result = orig
    }
    
    func BenchmarkAppendPreCapped(b *testing.B) {
        orig := make([]T, size)
        for n := 0; n < b.N; n++ {
            cpy := append(make([]T, 0, len(orig)), orig...)
            orig = cpy
        }
        result = orig
    }
    
    func BenchmarkAppendNil(b *testing.B) {
        orig := make([]T, size)
        for n := 0; n < b.N; n++ {
            cpy := append([]T(nil), orig...)
            orig = cpy
        }
        result = orig
    }
    
    func main() {}
    

    Output:

    $ go version
    go version devel +ffe33f1f1f17 Tue Nov 25 15:41:33 2014 +1100 linux/amd64
    $ go test -v -bench=.
    testing: warning: no tests to run
    PASS
    BenchmarkCopy                   200000        9983 ns/op
    BenchmarkAppend                 200000       10004 ns/op
    BenchmarkAppendPreCapped        200000       10077 ns/op
    BenchmarkAppendNil              200000        9960 ns/op
    ok      so/test 8.412s
    $ go test -v -bench=.
    testing: warning: no tests to run
    PASS
    BenchmarkCopy                   200000       10000 ns/op
    BenchmarkAppend                 200000       10112 ns/op
    BenchmarkAppendPreCapped        200000        9892 ns/op
    BenchmarkAppendNil              200000       10005 ns/op
    ok      so/test 8.422s
    $ go test -v -bench=.
    testing: warning: no tests to run
    PASS
    BenchmarkCopy                   200000        9967 ns/op
    BenchmarkAppend                 200000        9898 ns/op
    BenchmarkAppendPreCapped        200000       10123 ns/op
    BenchmarkAppendNil              200000       10022 ns/op
    ok      so/test 8.424s
    $ 
    

提交回复
热议问题