标记OS.Exit后不应出现无法访问的代码

时间:2019-05-29 19:38:55

标签: go

转到1.12窗口

将fmt.Println放到os.Exit之后而不是之前, 难道这不应该导致编译器失败或至少是警告吗?

package main

import (
    "fmt"
    "os"
)

func main() {
    fmt.Println("Hello, playground")
    os.Exit(0)
    fmt.Println("Good By, playground")
}

1 个答案:

答案 0 :(得分:2)

os.Exit()就像其他函数一样,编译器不应该知道它会终止应用程序,因此后面的其余代码是无法访问的。 os.Exit()仅是一个示例,还有更多示例,例如log.Fatal()(称为os.Exit())。更不用说您还可以创建一个调用其中之一的函数,编译器应该走多远才能检测到全部或大部分?

更进一步,Go编译器不会检测也不标记“真正的”不可达代码。使用return语句时,以下变化甚至可能对编译器很明显:

func main() {
    fmt.Println("Hello, playground")
    return
    fmt.Println("Good By, playground")
}

但是它可以编译并正常运行,并输出(在Go Playground上尝试):

Hello, playground

因此,编译器不会检测到无法访问的代码,而go vet会检测到,它也由Go Playground运行,因此您可以看到应用程序输出的前缀为:

./prog.go:10:2: unreachable code
Go vet exited.

此问题以前曾提出过,请参见cmd/gc: report unreachable code #9501。罗伯特·格里瑟默(Robert Grisemer)的回应是:

  

通常,Go的理念是不全力保护程序员免受错误的侵害。故意不为无法访问的代码引发错误。这也不是很常见的错误。此外,引入早期返回调试信息通常很有用,这可能会导致大量无法访问的代码。尚不清楚收益大于成本和不利。

     

未使用的变量可能会在简短的变量声明中与Go的重新声明机制一起导致微妙的查找错误-因此会出现未使用变量的错误消息。这是一种从经验演变而来的机制,是针对具体问题的务实解决方案。

     

报告了未使用的导入,因为它有助于保持对依赖关系的控制-这是大规模系统设计中的重要工具,并且副作用是,此方法还可以保持编译速度更快。再次是一个非常刻意的设计决定。

     

最后,使无效代码成为错误将是一种重大的语言更改,目前尚无法解决。

     

使用兽医。