0
votes

I am absolute newbie in Golang. I am learning through Tour of Go and then implementing ideas with my own understanding. I am having problem with goroutines. I made a unbuffered channel , then sent a string to that channel.

func main() {
    p := make(chan string)
    p <- "Hello goroutine"
    fmt.Println(<-p)
}

throws error

fatal error: all goroutines are asleep - deadlock!

I get it, channel is unbuffered. (That's the reason. Right?).

But when I refactor p <- "Hello goroutine to a goroutine

func main() {
    p := make(chan string)
    go sendHello(p)
    fmt.Println(<-p)
}

func sendHello(p chan string) {
    p <- "Hello goroutine"
}

It works without problem. I read that we do not need to use pointers with maps,slices and channels with most cases to modify the value. Was channel p passed to func sendHello(p chan string) via a copy which had a separate buffer. I still can not get my head around it.

1
I don't really understand your question. Your second example uses a goroutine, and this is why it doesn't block. So I'm not sure why you're speculating about copies of channels (which is entirely not what happens).Flimzy
This has nothing to do with pointers or passing around a copy. What happens: You span a new goroutine and while this goroutine works on sendHello the main go routine continues and waits until something is sent on p and reads this from p. The sending happens in the second goroutine.Volker
In your first code your program cannot advance once it reaches p <- "Hello" as no other goroutine is there to read. In your secon example you do have two groroutines, while one is trying to send the other is trying to read and the value will pass the channel. Again: This has nothing to do with how values are passed to functions, "references" or pointers.Volker
@Volker The println receives via <-p and does not exit without output. It shows outputtopenion
Sorry, I fixed the comment already.Volker

1 Answers

6
votes

Keep in mind that a channel has two ends, a sender and a receiver. Your problem is about the order of execution.

In the first example, when you use an unbuffered channel, the channel expects a receiver, while there's none as of sending Hello goroutine message, and waits until there's one (this is not the case for a buffered channel as it doesn't require to wait), and the execution never reaches the next line (i.e. a deadlock).

But in the second example, the receiver is bound to the channel and the groutine is executed after, and both sender and receiver don't remain in a wait state.