为什么这个声明是不可达的?

Why is this statement is unreachable?

这段代码是 the-way-to-go 的形式,我对频道示例感到困惑。为什么 for 循环后的语句无法访问,为什么当 ch 为空时 func getData 完成而没有恐慌?

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???
}

并输出:

./prog.go:32:5: unreachable code
Go vet exited.

Washington Tripoli London Beijing Tokio 
Program exited.

循环:

for {
    input = <-ch
    fmt.Printf("%s ", input)
}

从不退出(它永远循环),因此无法到达它后面的任何内容。为了使其可达,需要有一种方法来结束循环,即

for {
    input = <-ch
    fmt.Printf("%s ", input)
    if input == "fred" {
        break
    }
}
fmt.Printf("finished") // no longer unreachable

注意:这可能仍然会永远循环(如果“fred”从未在频道上发送,它将不会退出)。然而,这通常不能在编译时确定。

循环播放频道的常用方法是使用range;这将在频道关闭时退出:

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?

它不退出;它继续等待另一个值到达通道。但是根据 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.

因此,当您的 time.Sleep(1e9) 完成并且 main 退出 go 例程时 运行 getData 终止。

for {
    input = <-ch
    fmt.Printf("%s ", input)
}
fmt.Printf("finished") // unreachable, why???

for循环没有退出条件,内部也没有break,也就是说永远不会退出这个循环。这就是无法到达循环后的行的原因。