寶慕林4294392
2021-12-20 15:38:19
如果在 Go 中通過通道發(fā)送一個大結(jié)構(gòu)體,它實際上是在 goroutines 之間復(fù)制的嗎?例如,在下面的代碼中,Go 是否會在 goroutine 的生產(chǎn)者和消費者之間復(fù)制所有 largeStruct 數(shù)據(jù)?package mainimport ( "fmt" "sync")type largeStruct struct { buf [10000]int}func main() { ch := make(chan largeStruct) wg := &sync.WaitGroup{} wg.Add(2) go consumer(wg, ch) go producer(wg, ch) wg.Wait()}func producer(wg *sync.WaitGroup, output chan<- largeStruct) { defer wg.Done() for i := 0; i < 5; i++ { fmt.Printf("producer: %d\n", i) output <- largeStruct{} } close(output)}func consumer(wg *sync.WaitGroup, input <-chan largeStruct) { defer wg.Done() i := 0LOOP: for { select { case _, ok := <-input: if !ok { break LOOP } fmt.Printf("consumer: %d\n", i) i++ } }}游樂場:http : //play.golang.org/p/fawEQnSDwB
2 回答

不負(fù)相思意
TA貢獻(xiàn)1777條經(jīng)驗 獲得超10個贊
是的,Go 中的一切都是副本,您可以通過將通道更改為使用指針(又名chan *largeStruct
)來輕松解決該問題。
// 演示:http : //play.golang.org/p/CANxwt8s2B
如您所見,指向的指針v.buf
在每種情況下都不同,但是如果將其更改為chan *largeStruct
,則指針將相同。
@LucasJones 提供了一個更容易理解的例子:https : //play.golang.org/p/-VFWCgOnh0
正如@nos 指出的那樣,如果您在發(fā)送后修改兩個 goroutine 中的值,則存在潛在的競爭。

蕪湖不蕪
TA貢獻(xiàn)1796條經(jīng)驗 獲得超7個贊
send 語句在通道上發(fā)送一個值。通道表達(dá)式必須是通道類型,通道方向必須允許發(fā)送操作,并且要發(fā)送的值的類型必須可分配給通道的元素類型。
它是一個副本,因為該值是通過分配給通道的元素類型而發(fā)送到通道的。如果該值是一個結(jié)構(gòu)體,則復(fù)制該結(jié)構(gòu)體。如果該值是指向結(jié)構(gòu)的指針,則復(fù)制指向該結(jié)構(gòu)的指針。
- 2 回答
- 0 關(guān)注
- 204 瀏覽
添加回答
舉報
0/150
提交
取消