如果在GO中通过通道发送大型 struct ,那么它实际上是在goroutines之间复制的吗?

例如,在下面的代码中,Go会在goroutines生产者和消费者之间实际复制所有largeStruct数据吗?

package main

import (
    "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 := 0
LOOP:
    for {
        select {
        case _, ok := <-input:
            if !ok {
                break LOOP
            }
            fmt.Printf("consumer: %d\n", i)
            i++
        }
    }
}

操场:http://play.golang.org/p/fawEQnSDwB

推荐答案

是的,围棋中的所有东西都是副本,你可以很容易地通过改变频道来使用指针(也就是chan *largeStruct)来解决这个问题.

//demo:http://play.golang.org/p/CANxwt8s2B

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

@LucasJones提供了一个更容易遵循的示例:https://play.golang.org/p/-VFWCgOnh0

正如@nos所指出的,如果在发送后修改两个goroutine中的值,则可能存在竞争.

Go相关问答推荐

Go Regexp:匹配完整的单词或子字符串,或者根本不匹配

Go中的net.SplitHostPort(r.RemoteAddr)安全性

MaybeReadByte对通道的使用如何在Go中提供随机行为?

GO:如何指定类型约束,使S方法的参数类型与接收方的参数类型相同

如何在S汇编器中更高效地将全局数据加载到霓虹灯寄存器?

如何使用 Go 连接到非默认 firestore 数据库?

如何在 Go 中将 int 转换为包含 complex128 的泛型类型?

创建新对象后如何返回嵌套实体?

整理时转换值

Golang:如何判断通过缓冲通道进行通信时生产者或消费者是否较慢?

如何使用 fyne Go 使用 canvas.NewText() 使文本可滚动

获取切片元素的地址是否意味着 Go 中元素的副本?

如何使用struct的方法清除除某些字段之外的struct值

如何使用 math/big 对 bigInt 进行取模?

如何在测试中使用自定义标志(使用`testify/suite`)

使用反射在 struct 内迭代切片 struct

有没有办法在 golang 中定义可索引类型?

将 CSVExport 函数传递给处理程序 Gin

为什么 template.ParseFiles() 没有检测到这个错误?

不能使用 *T 类型的变量作为参数类型