FYI: It is possible for `done` to never be sent to. For example consider the following sequence:
goroutine: ch <- 1 main: <- 1 main: run defer main: fin = atomic load goroutine: atomic store main: not 1, return On Friday, August 18, 2017 at 11:13:36 AM UTC-7, bill....@talentinc.com wrote: > > Hi, > > https://play.golang.org/p/lR6_mxSjtb > > I have two long running things to do, I'd like to do them in parallel, > then sync up at the end. I've written it as a function which gets one thing > done, and which backgrounds the second thing with a goroutine. Thing one > has a lot of reasons to exit early, and I need to signal those to thing two > so that the go routine can exit cleanly and not create a goroutine leak. > Standard fare, usually solved by introducing a channel and a select > statement. I want to signal done for early exits, including panics, so I > thought I would write to the done channel in a defer block. That caused a > problem, because in the happy case, both the foreground and the background > routines are finished, the done channel has no reader, so writing to it in > the defer block causes "fatal error: all goroutines are asleep - deadlock!" > So I introduced a new boolean variable ("clean_finish") that is false until > the background job completes, and which is tested in the defer block before > writing to the done channel. Is there anything wrong with my approach? You > can see the code in the playground link above, or down below. > > > package main > > import ( > "sync/atomic" > "fmt" > "time" > ) > > func main() { > ch := make(chan int) > done := make(chan struct{}) > var clean_finish uint32 > defer func() { > fin := atomic.LoadUint32(&clean_finish) > if fin != 1 { > done <- struct{}{} > } > }() > go func() { > defer func() { > fmt.Println("we're done here") > }() > select { > case <-time.After(time.Second * 1): > ch <- 1 > atomic.StoreUint32(&clean_finish, 1) > case <- done: > fmt.Println("early exit") > } > }() > panic("bye") // comment this out to see normal behavior > n := <- ch > fmt.Printf("n: %v\n", n) > } > > -- 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+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.