golang -switch的默认表达式

z9ju0rcb  于 2023-09-28  发布在  Go
关注(0)|答案(1)|浏览(62)

参考:https://go101.org/quizzes/switch-1.html

package main

import "fmt"

func ExampleSwitchGo101_1() {
    f := func() bool {
        return false
    }

    switch f() // "{" is on next line, go compiler will insert a ";" here,
        // and the default switch value is true,

    {
    case true:
        fmt.Println(1)
    case false:
        fmt.Println(0)
    }
    // Output:
    // 1
}

输出是1而不是0。因为原文说switch的默认表达式是bool值true

问题:

1.这里有多少个switch语句?由于编译器在switch f()后面追加了一个“;”,所以我认为有2个。
1.但
2-1.如果我写switch f()没有大小写,那就是语法错误。
2-2.如果我编写{case ... }没有开关,也是语法错误。
1.如果这里只有1个switch,有人能解释一下语法吗?

uajslkp6

uajslkp61#

这是reportedmore than once before。这是一个自动的插入规则和开关表达式之间的奇怪的交互。
关于分号插入的规范说:
当输入被分解为标记时,如果行的最后一个标记是:

  • [...]
  • 运算符和标点符号++、--、)、]或}之一

因此,以函数调用(如f())结尾的行符合自动插入分号的条件,该行被重写为:

switch f();
{

那么这是一个带有空表达式的有效开关:
switch表达式前面可以有一个简单的语句,该语句在表达式被求值之前执行。

缺少的开关表达式等效于布尔值true
在形式语法中:

ExprSwitchStmt = "switch" [ SimpleStmt ";" ] [ Expression ] "{" { ExprCaseClause } "}" .

                                        ^ this is your auto-semicolon

因此,通过自动引入分号,switch表达式变为:

switch /* simple statement */ f(); /* missing switch expr (true) */ {
// ...
}

这非常类似于for语句,例如空的init、condition或post语句。

// valid
for i := 0; ;i++ {
}

// valid
for i := 0; i < 0; {

}

或甚至

// valid
if i := 0; f() // automatically inserts semicolon
{

但是如果你在这样的代码上运行go fmt,它应该移动前一行的花括号,所以最后在正确格式化的代码库中不太可能遇到这种令人困惑的代码。

相关问题