4

I understand the regular behavior of a channel is that it empties after a read. Is there a way to keep an unbuffered channel value for multiple reads without the value been removed from the channel?

For example, I have a goroutine that generates a single data for multiple down stream go routines to use. I don't want to have to create multiple channels or use a buffered channel which would require me to duplicate the source data (I don't even know how many copies I will need). Effectively, I want to be able to do something like the following:

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
}

EDIT Some feel this is a duplicate question. Perhaps, but not sure. The solution here seems simple in the end as n-canter pointed out. All it needs is for every go routine to "recycle" the data by putting it back to the channel after use. None of the supposedly "duplicates" provided this solution. Here is a sample:

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

Bruce
  • 163
  • 1
  • 4
  • 9
  • An unbuffered channel doesn't hold any values. How about adding the same value to a buffered channel multiple times? – JimB Mar 25 '17 at 00:48
  • That's a potential solution, but as I mentioned, I prefer not having to pump in multiple values. This is because a) I don't really know how many I will need. So I have to pump in extra; b) the data is rather large in size, don't want to duplicate as much:( – Bruce Mar 25 '17 at 00:57
  • It sounds like you just want to use a channel as a mutex around a single value, why not then just use a mutex? – JimB Mar 25 '17 at 01:14
  • JimB, I could use a mutex/global, but rather hard to manage because of the multiple source/target scenarios. – Bruce Mar 25 '17 at 01:44
  • jfly, I checked on your link, but they all seem to deal with regular channel behaviors. Couldn't find what I'm looking for here:( – Bruce Mar 25 '17 at 01:45

1 Answers1

2

You may readd value back to the channel after reading, but then all your gouroutines will read shared value sequentially and also you'll need some synchronization primitives for last goroutine not to block.

As far as I know the only case when you can use the single channel for broadcasting is closing it. In this case all readers will be notified.

If you don't want to duplicate large data, maybe you'd better use some global variable. But use it carefully, because it violates golang rule: "Don't communicate by sharing memory; share memory by communicating."

Also look at this question How to broadcast message using channel

Community
  • 1
  • 1
n-canter
  • 268
  • 1
  • 11
  • I feel this is the best solution so far. A little duplication, but at least not extra duplication - I don't have to create more that what I need. Thanks! – Bruce Mar 25 '17 at 01:46