I’m trying to isolate a deadlock problem in a bigger program and have reproduced my issue in the sample below (run it yourself here: https://play.golang.org/p/dHtc78LDDD)
package main
import "log"
type NotifyOp struct {
/** Channel to respond on once op completed */
response chan bool
}
type Hub struct {
doSomething chan *NotifyOp
}
func (h *Hub) run() {
log.Printf("Hub: Waiting for DoSomething")
notifyOp := <-h.doSomething
log.Printf("Hub: Doing Something")
notifyOp.response <- true
log.Printf("Hub: Done Something")
log.Printf("Hub: Finished")
}
type Client struct {
hub * Hub
finished chan bool
}
func (c *Client) run() {
op := NotifyOp{
response: make(chan bool) ,
}
log.Printf("Client: Calling Hub")
c.hub.doSomething <- &op
log.Printf("Client: Waiting on Finish")
<- op.response
log.Printf("Client: Done calling Hub")
c.finished <- true
log.Printf("Client: Finished")
}
func main() {
finishedChannel := make(chan bool)
hub := Hub{}
client := Client{
hub: &hub,
finished: finishedChannel,
}
go hub.run()
go client.run()
log.Printf("Main: Waiting on Finish")
<- finishedChannel
log.Printf("Main: Finished")
}
This outputs:
2009/11/10 23:00:00 Main: Waiting on Finish
2009/11/10 23:00:00 Client: Calling Hub
2009/11/10 23:00:00 Hub: Waiting for DoSomething
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/tmp/sandbox304437714/main.go:61 +0x160
goroutine 5 [chan receive (nil chan)]:
main.(*Hub).run(0x1040c108, 0x0)
/tmp/sandbox304437714/main.go:17 +0x80
created by main.main
/tmp/sandbox304437714/main.go:57 +0x100
goroutine 6 [chan send (nil chan)]:
main.(*Client).run(0x1040c110, 0x0)
/tmp/sandbox304437714/main.go:38 +0xe0
created by main.main
/tmp/sandbox304437714/main.go:58 +0x120
My question is why does this occur? I have some ideas, but I’m hoping that this will be obvious to more experienced go developers. Any pointers appreciated.