簡體   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