【问题标题】:Can go channel keep a value for multiple reads [duplicate]可以去通道为多次读取保留一个值[重复]
【发布时间】:2017-08-18 02:00:30
【问题描述】:

我了解通道的常规行为是在读取后清空。有没有办法在不从通道中删除值的情况下为多次读取保留一个无缓冲的通道值?

例如,我有一个 goroutine,它生成单个数据供多个下游 go 例程使用。我不想创建多个通道或使用缓冲通道,这需要我复制源数据(我什至不知道我需要多少副本)。实际上,我希望能够执行以下操作:

main{
   ch := make(ch chan dType)

   ch <- sourceDataGenerator()
   for _,_ := range DynamicRange{
      go TargetGoRoutine(ch)
   }
   close(ch)       // would want this to remove the value and the channel
}
func(ch chan dType) TargetGoRoutine{
   targetCollection <- ch    // want to keep the channel value after read
}

编辑 有些人认为这是一个重复的问题。也许,但不确定。正如 n-canter 指出的那样,这里的解决方案最终看起来很简单。它所需要的只是让每个 go 例程通过在使用后将数据放回通道来“回收”数据。没有一个所谓的“重复”提供了这个解决方案。这是一个示例:

package main
import (
  "fmt"
  "sync"
)

func main() {
 c := make(chan string)
 var wg sync.WaitGroup
    wg.Add(5)

 for i := 0; i < 5; i++ {
    go func(i int) {
        wg.Done()
        msg := <-c
        fmt.Printf("Data:%s, From go:%d\n", msg, i)
        c <-msg

    }(i)
}

   c <- "Original"
   wg.Wait()
   fmt.Println(<-c)
}

https://play.golang.org/p/EXBbf1_icG

【问题讨论】:

  • 无缓冲通道不保存任何值。将相同的值多次添加到缓冲通道怎么样?
  • 这是一个潜在的解决方案,但正如我所提到的,我宁愿不必输入多个值。这是因为 a) 我真的不知道我需要多少。所以我必须额外抽水; b) 数据比较大,不想重复太多:(
  • 听起来您只是想将通道用作围绕单个值的互斥体,为什么不直接使用互斥体呢?
  • JimB,我可以使用互斥锁/全局,但由于多个源/目标场景很难管理。
  • jfly,我查看了您的链接,但它们似乎都处理常规频道行为。在这里找不到我要找的东西:(

标签: multithreading go channel


【解决方案1】:

您可以在读取后将值读回通道,但是您的所有 gouroutine 将顺序读取共享值,并且您需要一些同步原语以使最后一个 goroutine 不阻塞。

据我所知,您可以使用单个频道进行广播的唯一情况是关闭它。在这种情况下,所有读者都会收到通知。

如果你不想复制大数据,也许你最好使用一些全局变量。但是要小心使用,因为它违反了 golang 规则:“不要通过共享内存进行通信;通过通信来共享内存。”

也看这个问题How to broadcast message using channel

【讨论】:

  • 我觉得这是迄今为止最好的解决方案。一点点重复,但至少不是额外的重复——我不必创造更多我需要的东西。谢谢!
猜你喜欢
  • 2023-01-10
  • 2012-06-14
  • 2011-04-20
  • 1970-01-01
  • 2019-09-05
  • 2011-08-10
  • 2016-09-10
  • 1970-01-01
  • 2020-07-24
相关资源
最近更新 更多