golang 的失败似乎出乎意料

dom*_*ato 5 go switch-statement fall-through

我有以下代码:

package main

import (
    "fmt"
)

func main() {
    switch {
    case 1 == 1:
        fmt.Println("1 == 1")
        fallthrough
    case 2 == 1:
        fmt.Println("2 == 1")
    }
}
Run Code Online (Sandbox Code Playgroud)

在 go 操场上打印两行 -请参阅此处的示例。我本来希望 fallthrough 语句包括对下一个case语句的评估,但情况似乎并非如此。

当然,我总是可以使用一堆if语句,所以这不是一个真正的障碍,但我很好奇这里的意图是什么,因为在我看来这不是一个明显的结果。

有人愿意解释吗?例如:在这段代码中,我怎样才能让第 1 和第 3 种情况执行?

Sev*_*eva 7

Switch 不是一堆如果。它更类似于if {} else if {}构造,但有一些变化 - 即breakfallthrough。不可能让 switch 执行第一种和第三种情况 - switch 不会检查每个条件,它会找到第一个匹配项并执行它。就这样。

它的主要目的是遍历可能值的列表并为每个值执行不同的代码。事实上,在C(switch 语句的来源)中,switch 表达式只能是整型,并且 case 值也只能是 switch 表达式将进行比较的常量。直到最近,语言才开始在 switch case 中添加对字符串、布尔表达式等的支持。

至于fallthrough逻辑,它也来自C。C中没有fallthrough运算符。在C中,除非遇到break运算符,否则执行会陷入下一个case(不检查case值)。这种设计的原因是有时您需要做一些特殊的事情,然后执行与其他情况相同的步骤。所以,这个设计只是允许这样做。不幸的是,它很少有用,因此当程序员忘记放入break语句时,默认情况下失败会导致更多麻烦,然后当真正有意省略该break时实际上会有所帮助。因此,许多现代语言改变了这种逻辑,默认情况下永远不会失败,并且如果确实需要失败,则需要显式的失败声明。

不幸的是,很难想出一个足够短以适合答案的非人为的失败示例。正如我所说,这种情况相对罕见。但有时你需要编写类似这样的代码:

if x == a || x == b {
  if x == a {
    // do action a
  }
  // do action ab
} else if x == c {
   // do action c
} else if x == d {
  // do action d
}
Run Code Online (Sandbox Code Playgroud)

事实上,我最近在我的一个项目中需要类似结构的代码。所以,我改用 switch 语句。它看起来像这样:

switch x {
  case a: // do action a
          fallthrough
  case b: // do action ab
  case c: // do action c
  case d: // do action d
}
Run Code Online (Sandbox Code Playgroud)

从问题中切换出来的功能与此相同:

if 1 == 1 || 2 == 1 {
    if 1 == 1 {
        fmt.Println("1 == 1")
    }
    fmt.Println("2 == 1")
}
Run Code Online (Sandbox Code Playgroud)


Ruf*_*ind 5

据推测,Go 的失败行为是模仿 C 的,C 总是这样工作的。在 C 中,switch语句只是条件 goto 链的简写,因此您的特定示例将被编译,就好像它是这样写的:

    # Pseudocode
    if 1 == 1 goto alpha
    if 2 == 1 goto beta
alpha:
    fmt.Println("1 == 1")
beta:
    fmt.Println("2 == 1")
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,一旦执行进入案例alpha,它就会继续向下流动,忽略beta标签(因为标签本身并没有真正做任何事情)。条件检查已经发生并且不会再发生。

因此,fallthrough 语句的非直观本质switch仅仅是因为switch语句是几乎不加掩饰的 goto 语句。