繁体   English   中英

Golang切片追加和重新分配

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM