FAQ
This is a "design pattern" question. I have a program that runs several
independent goroutines. They're all long-lived, discovering stuff about the
world, and occasionally one or more of them will discover things that the
others all want to know. Setting a global boolean to true is an obvious
solution, but I'd like to make my little goroutines easily testable, with
all their input coming from their parameters and no peeking at outside
state.

It seems like I need to pass each goroutine two channels: one on which
it'll be notified of events, and one on which it can send to notify the
world about what it's found. I'll need a goroutine whose job is to listen
for events on the latter, and broadcast them to the former.

Is there a cleaner, better, more idiomatic way to do this?

Thanks!
Baron

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

  • Felix Zilla at Dec 2, 2013 at 1:15 am
    hmm, Been trying some ideas but is either the go routines are all asleep or
    nothing.
    still on it

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Luzon83 at Dec 2, 2013 at 1:36 am

    On Sunday, December 1, 2013 9:19:23 PM UTC+1, Baron Schwartz wrote:

    It seems like I need to pass each goroutine two channels: one on which
    it'll be notified of events, and one on which it can send to notify the
    world about what it's found. I'll need a goroutine whose job is to listen
    for events on the latter, and broadcast them to the former.

    Is there a cleaner, better, more idiomatic way to do this?
    No, I'd say that's exactly what channels are there for.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Jsor at Dec 2, 2013 at 1:53 am
    The way I always thought would be good to do this is dot parts of the
    goroutine where the info would be useful with:

    select {
    case info := <-notifyChan:
       // stuff
    default:
    }

    That way you maintain the fact that sharing things isn't required and
    alleviates the "everything is asleep" problem. It does get a bit more
    complex when you want to filter what goroutines get what information, you
    need some sort of way to tag updates and some sort of manager to dispatch
    them to the right channels. (I guess you could send it to all of them and
    have each goroutine filter it individually, but I feel like a manager is a
    cleaner solution in the majority of cases).

    I have found that in most cases it ends up a bit cleaner than a blackboard
    pattern, though usually the ideal solution is to have a blackboard for some
    data (usually more persistent data, or data that other agents that don't
    exist yet may need at a later date), and channel updates for other data.
    On Sunday, December 1, 2013 6:36:54 PM UTC-7, luz...@gmail.com wrote:
    On Sunday, December 1, 2013 9:19:23 PM UTC+1, Baron Schwartz wrote:

    It seems like I need to pass each goroutine two channels: one on which
    it'll be notified of events, and one on which it can send to notify the
    world about what it's found. I'll need a goroutine whose job is to listen
    for events on the latter, and broadcast them to the former.

    Is there a cleaner, better, more idiomatic way to do this?
    No, I'd say that's exactly what channels are there for.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Ask Bjørn Hansen at Dec 2, 2013 at 2:03 am
    I always end up with something like this in my daemon-like programs. It
    never feels entirely satisfying as it always seems like surprisingly much
    boiler-plate code.

    One variation on this I've liked is to have the channel be an interface{}
    and then use the type of the message to signal the event (vs having a
    particular "ControlMessage" type). I suspect doing it this way would also
    make it easier to generalize more of the code into a package ...


    Ask

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Kevin Gillette at Dec 2, 2013 at 2:17 am

    On Sunday, December 1, 2013 1:19:23 PM UTC-7, Baron Schwartz wrote:
    Setting a global boolean to true is an obvious solution
    Unless that boolean is protected by a mutex (or a legitimate alternative to
    a mutex), doing so will introduce a race condition. Additionally, unless
    the bool gets flipped "on" but never gets flipped off again, additional
    trickiness will be introduced.

    It seems like I need to pass each goroutine two channels: one on which
    it'll be notified of events, and one on which it can send to notify the
    world about what it's found. I'll need a goroutine whose job is to listen
    for events on the latter, and broadcast them to the former.
    This is a reasonable approach, and is idiomatic.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Roger peppe at Dec 2, 2013 at 2:53 pm

    On 1 December 2013 20:19, Baron Schwartz wrote:
    This is a "design pattern" question. I have a program that runs several
    independent goroutines. They're all long-lived, discovering stuff about the
    world, and occasionally one or more of them will discover things that the
    others all want to know. Setting a global boolean to true is an obvious
    solution, but I'd like to make my little goroutines easily testable, with
    all their input coming from their parameters and no peeking at outside
    state.

    It seems like I need to pass each goroutine two channels: one on which it'll
    be notified of events, and one on which it can send to notify the world
    about what it's found. I'll need a goroutine whose job is to listen for
    events on the latter, and broadcast them to the former.

    Is there a cleaner, better, more idiomatic way to do this?
    For a similar kind of problem, I implemented code.google.com/p/rog-go/values .
    In particular you might be able to use
    http://godoc.org/code.google.com/p/rog-go/values#Value
    (the Lens type just provides a way for several watchers to obtain
    different read-writable views of the same value).

    This works OK when events are all of the form "set x to y", so intermediate
    events can be discarded without loss of information.

    When events are deltas to an existing state, a channel is
    probably going to be a better fit. You will however need to be very
    careful to avoid deadlock when two of your goroutines both decide
    they need to inform each other of something at the same moment.

       cheers,
         rog.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Ingo Oeser at Dec 3, 2013 at 10:13 am
    I still don't understand enough about the problem. So I will ask some stupid questions first.

    Who is starting those goroutines? Who is creating those global channels? How are goroutine creation and channel creation related in your program?

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Baron Schwartz at Dec 3, 2013 at 3:45 pm
    I would do all of that in main() and start another goroutine in main() to
    coordinate amongst them. I will be doing this in the next day or two and
    will probably write a blog post about it. I'll write back with a link if I
    do.

    - Baron
    On Tue, Dec 3, 2013 at 5:13 AM, Ingo Oeser wrote:

    I still don't understand enough about the problem. So I will ask some
    stupid questions first.

    Who is starting those goroutines? Who is creating those global channels?
    How are goroutine creation and channel creation related in your program?
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Baron Schwartz at Dec 17, 2013 at 8:56 pm
    Here's the promised blog post. We open-sourced the library we used to do
    this.
    https://vividcortex.com/blog/2013/12/17/multitick-multiple-subscriber-time-ticker-in-go/

    On Tue, Dec 3, 2013 at 10:45 AM, Baron Schwartz wrote:

    I would do all of that in main() and start another goroutine in main() to
    coordinate amongst them. I will be doing this in the next day or two and
    will probably write a blog post about it. I'll write back with a link if I
    do.

    - Baron

    On Tue, Dec 3, 2013 at 5:13 AM, Ingo Oeser wrote:

    I still don't understand enough about the problem. So I will ask some
    stupid questions first.

    Who is starting those goroutines? Who is creating those global channels?
    How are goroutine creation and channel creation related in your program?
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedDec 1, '13 at 8:19p
activeDec 17, '13 at 8:56p
posts10
users8
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase