Struct 如何有效地通过通道将goroutine中分配的结构传递回主例程?

Struct 如何有效地通过通道将goroutine中分配的结构传递回主例程?,struct,go,channel,Struct,Go,Channel,基本上,我有一个主例程,它生成多个goroutine来处理数据。每次goroutine处理数据时,它都会发回一个大小不同的结构(每次都包含从goroutine中分配的片和/或数组) 数据不是很大(比如说,几兆字节),但一般来说,将指针传输到数据比将其全部拷贝更有效(安全吗)?如果数据结构是静态的,并且我向它传输了一个指针,那么在我仍在处理上一次调用的结果时,结构可能会发生变化(如果它完全重新分配,那么这可能不是问题)。向值发送指针是正常且常见的。如果该值较大,则发送指向该值的指针将比发送该值更有

基本上,我有一个主例程,它生成多个goroutine来处理数据。每次goroutine处理数据时,它都会发回一个大小不同的结构(每次都包含从goroutine中分配的片和/或数组)


数据不是很大(比如说,几兆字节),但一般来说,将指针传输到数据比将其全部拷贝更有效(安全吗)?如果数据结构是静态的,并且我向它传输了一个指针,那么在我仍在处理上一次调用的结果时,结构可能会发生变化(如果它完全重新分配,那么这可能不是问题)。

向值发送指针是正常且常见的。如果该值较大,则发送指向该值的指针将比发送该值更有效。运行一个基准来找出“大”有多大

需要注意的是,必须防止对值的不安全并发访问。防止不安全并发访问的常见策略有:

  • 将值的所有权从发送方传递给接收方。发送方在发送值后不访问该值。接收者可以用这个值做任何它想做的事情
  • 发送后将该值视为只读。发送方或接收方都不会在发送后修改该值
据我所知,您正在尝试执行以下操作:

func watchHowISoar() (ch chan *bigData) {
    ch = make(chan *bigData)
    go func() {
        for i := 0; i < 10; i++ {
            bd := &bigData{i}
            ch <- bd
            // as long as you don't modify bd inside this goroutine after sending it, you're safe.
        }
        close(ch)
    }()
    return
}
func main() {
    for iamaleafOnTheWind := range watchHowISoar() {
        fmt.Printf("%p\n", iamaleafOnTheWind)
    }
}
func watchHowISoar()(ch chan*bigData){
ch=制造(chan*bigData)
go func(){
对于i:=0;i<10;i++{
bd:=&bigData{i}

我们需要更多的细节,这个结构是什么样的,为什么在你发送它之后还要修改它?发送一个指针是安全的,但是如果你从不同的goroutine中修改它,你仍然会以一个竞赛结束。我实际上是从接收者那里读到的,但是如果它是一个指向静态结构的指针,我会期望一个race cond这可能是一种风险。如果它是一个指向goroutine中新创建的内容的指针(例如,通过new创建的结构或通过make()创建的数组/切片),则应该干净地传递给接收方(发送方不会再修改该特定指针).MB大小的结构将非常大。您可能希望在那里使用指针。但是,您不能使用可变大小的结构。如果您使用切片传递结构,并且担心修改,指针或副本不会对共享可变性产生影响。是否每次都通过make()在goroutine中创建结构(正如我已经做的)然后发送指针(而不是实际数据)满足传递所有权的要求?我希望在这种情况下,每次调用的指针都会不同。是的,对于new-对于post,我简化了我的原始问题,其中涉及通过反射发送和解析的切片,这是由于一个特殊的select构造…违反了我的条件。:-DIt可能是一个大结构…这就是为什么我想更熟悉with Go如何在我学习最佳实践的同时管理指针。@MartyMacGyver只要你调用
make
,每次都返回一个新的切片,而且你不必返回指向切片的指针,你可以安全地复制它,它将指向内存中的相同数据。一般来说,可以使用其他类型(
string
map
s,
interface
s)内部也包含指针:请看,这是我的常规,rambly.Firefly奖励积分!有趣-我的想法很相似(感谢一个干净的例子!仍在这里学习),但每次创建新频道时(如果我读对了的话)我使用的是一个持久通道,但每次都发送一个新分配的数据结构(这样读卡器就不会在下一次调用goroutine时(可能是在读卡器仍在读卡器时)指向被更改的数据)@MartyMacGyver否频道只创建一次,watchHowISoar只被调用一次,然后for循环在返回的频道上循环。只要您在每次发送之前分配“数据”,就可以了。