Warm tip: This article is reproduced from serverfault.com, please click

Why is this statement is unreachable?

发布于 2020-11-28 09:13:07

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.
Questioner
LeChauvet
Viewed
0
Brits 2020-11-28 17:30:35

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.