I am trying to learn Go and I was experimenting in the playground. I have a very simple go code. I was trying to use Structs and Slices together in a go routine. I am not sure if this will be a thing I will use in production but it seemed a little off, so here:
func main() {
routinemsg := make(chan []Person)
routinemsg2 := make(chan []Person)
// create the person records
p1 := newPerson("john doe", 25)
p2 := newPerson("dohn joe", 52)
p3 := newPerson("bohn joo", 30)
// send a slice of Person to the first routine
go func() { routinemsg <- []Person{p1, p2} }()
// retrieve the slice from the first routine[in the append]
// append p3 to the slice retrieved from the first routine
// send the new slice to the second routine
go func() { routinemsg2 <- append(<-routinemsg, p3) }()
// I am able to see the first Println but when I insert the second one I get a deadlock error
// also, same error if I use one Println with 2 arguments.
fmt.Println(<-routinemsg)
fmt.Println(<-routinemsg2)
}
I heard about wait groups but dont know them yet! So, be nice to me :D and thanks for your time
CodePudding user response:
There is only a single send operation on routinemsg
, but you have 2 receive operations from it: one in a launched goroutine and another in the main
goroutine. A sent value can only be received once, by one receiver.
If the launched goroutine receives from routinemsg
first, then it will be a deadlock: the receive in the main
will block forever.
If the main
goroutine would receive first, then the launched goroutine would block forever (trying to receive from it), hence it could never sending anything on routinemsg2
, hence the receive from routinemsg2
in main
would also block forever: deadlock again.
Remove the fmt.Println(<-routinemsg)
line in main()
, and then the final receive from routinemsg2
can (eventually) proceed and will print the slice holding p1
, p2
and p3
:
[{john doe 25} {dohn joe 52} {bohn joo 30}]
Try it on the Go Playground.