This code is form the-way-to-go, I'm confused with the example of channels. Why is the statement after for loop is unreachable and why the func getData finishes without panic when ch gets empty?
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan string)
go sendData(ch)
go getData(ch)
time.Sleep(1e9)
}
func sendData(ch chan string) {
ch <- "Washington"
ch <- "Tripoli"
ch <- "London"
ch <- "Beijing"
ch <- "Tokio"
}
func getData(ch chan string) {
var input string
// time.Sleep(2e9)
for {
input = <-ch
fmt.Printf("%s ", input)
}
fmt.Printf("finished") // unreachable, why???
}
and output:
./prog.go:32:5: unreachable code
Go vet exited.
Washington Tripoli London Beijing Tokio
Program exited.
The loop:
for {
input = <-ch
fmt.Printf("%s ", input)
}
never exits (it loops for ever) so anything following it cannot be reached. To make it reachable there needs to be a way for the loop to end i.e.
for {
input = <-ch
fmt.Printf("%s ", input)
if input == "fred" {
break
}
}
fmt.Printf("finished") // no longer unreachable
Note: It is possible that this will still loop for ever (if "fred" is never sent on the channel it will not exit). However this cannot generally be determined at compile time.
A common way of looping with channels is to use range
; this will exit when the channel is closed:
for input = range ch {
fmt.Printf("%s ", input)
}
fmt.Printf("finished") // no longer unreachable
and why the func getData finishes without panic when ch gets empty?
It doesn't exit; it's continues to wait for another value to arrive on the channel. However as per the spec:
Program execution begins by initializing the main package and then invoking the function main. When that function invocation returns, the program exits. It does not wait for other (non-main) goroutines to complete.
So when your time.Sleep(1e9)
is done and main exits the go routine running getData
is terminated.