这段代码有什么意义:
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
来自此页面:http://blog.golang.org/go-slices-usage-and-internals,并且应该增加一个切片。但是,上面的代码片段是一个图表,它将切片描述为具有指针,长度和容量的结构。为什么必须复制每个单独的条目而不是像:
t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
t = s[:]
s = t
如果问题是t
的容量变为与s
相同,为什么还有另一种方法将指针设置为相同。或者切片是否有指向数组中每个元素的指针?
编辑:我进一步阅读并得到了这段代码:
func CopyDigits(filename string) []byte {
b, _ := ioutil.ReadFile(filename)
b = digitRegexp.Find(b)
c := make([]byte, len(b))
copy(c, b)
return c
}
其目的是在使用c
返回copy
后停止引用该文件。这是否意味着copy
复制基础数组以及切片?
答案 0 :(得分:8)
构造一个新的,容量更大的底层数组,其长度和值与旧的底层数组相同。旧的底层数组将由垃圾收集器回收。例如,
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)])
}
输出:
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]
The Go Programming Language Specification
Appending to and copying slices
函数副本将切片元素从源src复制到 destination 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 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)])
}
输出:
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]