为了账号安全,请及时绑定邮箱和手机立即绑定

如果通过 Golang 通道发送,结构是否实际上在 goroutine 之间复制?

如果通过 Golang 通道发送,结构是否实际上在 goroutine 之间复制?

Go
宝慕林4294392 2021-12-20 15:38:19
如果在 Go 中通过通道发送一个大结构体,它实际上是在 goroutines 之间复制的吗?例如,在下面的代码中,Go 是否会在 goroutine 的生产者和消费者之间复制所有 largeStruct 数据?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 回答

?
不负相思意

TA贡献1777条经验 获得超10个赞

是的,Go 中的一切都是副本,您可以通过将通道更改为使用指针(又名chan *largeStruct)来轻松解决该问题。

// 演示:http : //play.golang.org/p/CANxwt8s2B

如您所见,指向的指针v.buf在每种情况下都不同,但是如果将其更改为chan *largeStruct,则指针将相同。

@LucasJones 提供了一个更容易理解的例子:https : //play.golang.org/p/-VFWCgOnh0

正如@nos 指出的那样,如果您在发送后修改两个 goroutine 中的值,则存在潜在的竞争。


查看完整回答
反对 回复 2021-12-20
?
芜湖不芜

TA贡献1796条经验 获得超7个赞

Go 编程语言规范

发送报表

send 语句在通道上发送一个值。通道表达式必须是通道类型,通道方向必须允许发送操作,并且要发送的值的类型必须可分配给通道的元素类型。

它是一个副本,因为该值是通过分配给通道的元素类型而发送到通道的。如果该值是一个结构体,则复制该结构体。如果该值是指向结构的指针,则复制指向该结构的指针。


查看完整回答
反对 回复 2021-12-20
  • 2 回答
  • 0 关注
  • 209 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号