Go 复制切片有什么意义?

Go 复制切片有什么意义?,go,Go,这段代码的要点是什么: t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0 for i := range s { t[i] = s[i] } s = t func CopyDigits(filename string) []byte { b, _ := ioutil.ReadFile(filename) b = digitRegexp.Find(b) c := make([]byte

这段代码的要点是什么:

t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
for i := range s {
    t[i] = s[i]
}
s = t
func CopyDigits(filename string) []byte {
    b, _ := ioutil.ReadFile(filename)
    b = digitRegexp.Find(b)
    c := make([]byte, len(b))
    copy(c, b)
    return c
}
这是从这页:,应该是增长一片。然而,在代码片段上方是一个图表,它将一个切片描述为一个具有指针、长度和容量的结构。为什么每个条目都必须复制过来,而不是像这样:

t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
t = s[:]
s = t
如果问题是
t
的容量更改为与
s
相同,为什么没有其他方法将指针设置为相同。或者一个切片是否有一个指针,指向其边界内数组中的每个元素

编辑:我读了进一步的内容,得到了以下代码片段:

t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
for i := range s {
    t[i] = s[i]
}
s = t
func CopyDigits(filename string) []byte {
    b, _ := ioutil.ReadFile(filename)
    b = digitRegexp.Find(b)
    c := make([]byte, len(b))
    copy(c, b)
    return c
}

其目的是在使用
copy
返回
c
后停止引用文件。这是否意味着
copy
复制底层数组以及切片?

以构建一个新的、容量更大的底层数组,其长度和值与旧的底层数组相同。旧的底层数组将由垃圾收集器回收。比如说,

package main

import "fmt"

func main() {
    s := []byte{0, 1, 2, 3, 4}[:3]
    fmt.Printf("s: %p %d %v %d %v\n", &s[0], len(s), s, cap(s), s[:cap(s)])
    t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
    fmt.Printf("t: %p %d %v %d %v\n", &t[0], len(t), t, cap(t), t[:cap(t)])
    for i := range s {
        t[i] = s[i]
    }
    s = t
    fmt.Printf("s: %p %d %v %d %v\n", &s[0], len(s), s, cap(s), s[:cap(s)])
    fmt.Printf("t: %p %d %v %d %v\n", &t[0], len(t), t, cap(t), t[:cap(t)])
}
package main

import "fmt"

func Copy() []byte {
    b := []byte{0, 1, 2, 3, 4, 5, 6, 7}
    fmt.Printf("b: %p %d %v %d %v\n", &b[0], len(b), b, cap(b), b[:cap(b)])
    b = b[:2]
    fmt.Printf("b: %p %d %v %d %v\n", &b[0], len(b), b, cap(b), b[:cap(b)])
    c := make([]byte, len(b))
    copy(c, b)
    fmt.Printf("c: %p %d %v %d %v\n", &c[0], len(c), c, cap(c), c[:cap(c)])
    return c
}

func main() {
    d := Copy()
    fmt.Printf("d: %p %d %v %d %v\n", &d[0], len(d), d, cap(d), d[:cap(d)])
}
输出:

s: 0x10500168 3 [0 1 2] 5 [0 1 2 3 4]
t: 0x1052e130 3 [0 0 0] 12 [0 0 0 0 0 0 0 0 0 0 0 0]
s: 0x1052e130 3 [0 1 2] 12 [0 1 2 0 0 0 0 0 0 0 0 0]
t: 0x1052e130 3 [0 1 2] 12 [0 1 2 0 0 0 0 0 0 0 0 0]
b: 0x10500168 8 [0 1 2 3 4 5 6 7] 8 [0 1 2 3 4 5 6 7]
b: 0x10500168 2 [0 1] 8 [0 1 2 3 4 5 6 7]
c: 0x10500178 2 [0 1] 2 [0 1]
d: 0x10500178 2 [0 1] 2 [0 1]

函数copy将切片元素从源src复制到源src 目标dst并返回复制的元素数。二者都 参数必须具有相同的元素类型T,并且必须可分配给 []T类型的切片。复制的元素数是 len(src)和len(dst)

示例:

var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
var s = make([]int, 6)
var b = make([]byte, 5)
n1 := copy(s, a[0:])            // n1 == 6, s == []int{0, 1, 2, 3, 4, 5}
n2 := copy(s, s[2:])            // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}
n3 := copy(b, "Hello, World!")  // n3 == 5, b == []byte("Hello")
如果我们返回对
b
的引用,我们将为
b
锁定整个底层数组。由于
b
引用的是一个文件,因此很可能是兆字节或千兆字节。通过返回一个新的底层数组
c
,它是该数字的精确大小,即几个字节,将不再有对
b
的大型底层数组的引用,垃圾收集器将回收该数组。
copy
内置函数将值从
b
复制到
c
。比如说,

package main

import "fmt"

func main() {
    s := []byte{0, 1, 2, 3, 4}[:3]
    fmt.Printf("s: %p %d %v %d %v\n", &s[0], len(s), s, cap(s), s[:cap(s)])
    t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
    fmt.Printf("t: %p %d %v %d %v\n", &t[0], len(t), t, cap(t), t[:cap(t)])
    for i := range s {
        t[i] = s[i]
    }
    s = t
    fmt.Printf("s: %p %d %v %d %v\n", &s[0], len(s), s, cap(s), s[:cap(s)])
    fmt.Printf("t: %p %d %v %d %v\n", &t[0], len(t), t, cap(t), t[:cap(t)])
}
package main

import "fmt"

func Copy() []byte {
    b := []byte{0, 1, 2, 3, 4, 5, 6, 7}
    fmt.Printf("b: %p %d %v %d %v\n", &b[0], len(b), b, cap(b), b[:cap(b)])
    b = b[:2]
    fmt.Printf("b: %p %d %v %d %v\n", &b[0], len(b), b, cap(b), b[:cap(b)])
    c := make([]byte, len(b))
    copy(c, b)
    fmt.Printf("c: %p %d %v %d %v\n", &c[0], len(c), c, cap(c), c[:cap(c)])
    return c
}

func main() {
    d := Copy()
    fmt.Printf("d: %p %d %v %d %v\n", &d[0], len(d), d, cap(d), d[:cap(d)])
}
输出:

s: 0x10500168 3 [0 1 2] 5 [0 1 2 3 4]
t: 0x1052e130 3 [0 0 0] 12 [0 0 0 0 0 0 0 0 0 0 0 0]
s: 0x1052e130 3 [0 1 2] 12 [0 1 2 0 0 0 0 0 0 0 0 0]
t: 0x1052e130 3 [0 1 2] 12 [0 1 2 0 0 0 0 0 0 0 0 0]
b: 0x10500168 8 [0 1 2 3 4 5 6 7] 8 [0 1 2 3 4 5 6 7]
b: 0x10500168 2 [0 1] 8 [0 1 2 3 4 5 6 7]
c: 0x10500178 2 [0 1] 2 [0 1]
d: 0x10500178 2 [0 1] 2 [0 1]