Home > Enterprise >  Deadlock when using two fmt.printlns with a go routine?
Deadlock when using two fmt.printlns with a go routine?

Time:11-26

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.

  • Related