[英]Golang slice append and reallocation
我最近一直在学习go,并且对重新分配发生时切片的行为有疑问。 假设我有一个指向结构的指针,例如:
var a []*A
如果我要将这个slice传递给另一个函数,并且我的理解是,它将在内部通过值传递slice头,该header在一个单独的goroutine上运行,并且仅从slice读取,而启动goroutine的函数继续追加到切片,有问题吗? 例如:
package main
type A struct {
foo int
}
func main() {
a := make([]*A, 0, 100)
ch := make(chan int)
for i := 0; i < 100; i++ {
a = append(a, &A{i})
}
go read_slice(a, ch)
for i := 0; i < 100; i++ {
a = append(a, &A{i+100})
}
<-ch
}
func read_slice(a []*A, ch chan int) {
for i := range a {
fmt.Printf("%d ", a[i].foo)
}
ch <- 1
}
因此,根据我的理解,由于read_slice()函数在自己的goroutine上带有slice头的副本运行,因此它具有指向当前后备数组的底层指针,以及调用该函数时可以访问的大小。的。
但是,当另一个goroutine附加到切片时,如果超出容量,它将触发重新分配。 go运行时是否不会将内存分配给read_slice()中使用的旧支持数组,因为该函数中有对它的引用?
我尝试使用“ go run -race slice.go”运行它,但是没有报告任何内容,但是我觉得我在这里可能做错了什么? 任何指针将不胜感激。
谢谢!
在没有对后备阵列的引用之前,GC不会收集后备阵列。 该程序中没有种族。
考虑没有goroutines的情况:
a := make([]*A, 0, 100)
for i := 0; i < 100; i++ {
a = append(a, &A{i})
}
b := a
for i := 0; i < 100; i++ {
b = append(b, &A{i+100})
}
当追加到b
分配新的支持数组时,切片a
将继续使用前100个指针来引用支持数组。 切片a
不会悬空地指向后备阵列。
现在将goroutine添加到方案中:
a := make([]*A, 0, 100)
for i := 0; i < 100; i++ {
a = append(a, &A{i})
}
b := a
go read_slice(a, ch)
for i := 0; i < 100; i++ {
b = append(b, &A{i+100})
}
goroutine可以愉快地使用slice a
。 没有悬挂的参考。
现在考虑问题中的程序。 它的功能与此处的最后一个片段相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.