文章原文链接为 https://blog.devtrovert.com/p/switch-in-go-6-ways-to-use-it
照片由 Zbyněk Skrčený 在 Unsplash 上拍摄
Go 以其简单而闻名,但我注意到并不是每个人都熟悉 switch
语句在这种语言中的多功能性。
首先,如果您不熟悉 Go 的 switch
语句,与其他语言相比,它可能看起来有点不同。这是一个简单的例子来展示它的样子:
func main() {
var i int = 1
switch i {
case 1:
fmt.Println("i is 1")
case 2:
fmt.Println("i is 2")
default:
fmt.Println("i is not 1 or 2")
}
}
Go 的 switch 的一个很酷的事情是,一旦找到匹配项,它就会停止,你不需要在每个 case 的末尾添加一个 break 语句。
但不仅仅如此。
Go 中的 switch 语句有两部分:分号之前的部分是初始化器,分号之后的部分是我们要检查的值。
我们可以选择同时使用、使用其中之一或都不使用:
switch initializer; value {}
switch initializer {}
switch value {}
switch {}
有趣,对吧?
1. 布尔值
有时,您可能会使用带有变量的 switch
语句,但这里有一种不同的方法。
考虑使用布尔值的switch。这种方法让我们可以检查多个条件,而不必只依赖于一个变量的值:
func main() {
var a int = 1
var b int = 2
switch true { // <--- use true literal
case a == 1 && b == 2:
fmt.Println("a is 1 and b is 2")
case a == 3:
fmt.Println("a is 3"):
default:
fmt.Println("a is not 1 or 3")
}
}
乍一看, switch true
似乎没有必要且毫无意义。
感觉有点像我们在陈述显而易见的事情,但好消息是 Go 有一种更简化的方法来处理这个问题,你实际上可以像这样简化它:
switch { // <--- just remove `true`
case a == 1 && b == 2:
...
}
这种简化的方法也同样有效。
此外,switch 语句可以与“false”文字一起使用,提供一种确定哪些条件不满足的方法。
2. 初始化值
通常,我们会忽略 switch 语句中的初始化部分。
但它非常有用,并且与 if
语句或 for
循环中的初始值设定项类似。它允许您声明并分配一个变量,然后立即使用它。
下面是一个例子来说明这一点:
switch a := 1; a {
case 1:
fmt.Println("a is 1")
}
// similar
if a := 1; a == 1 {
fmt.Println("a is 1")
}
在这些情况下, a
的范围仅限于 switch 语句,这意味着您不能在其外部使用。
还记得我们如何忽略开关的两个部分吗?
那么,您也可以选择仅使用初始值设定项部分,当您执行此操作时,值部分被假定为 true
:
switch a := 1 {
case a == 1:
fmt.Println("a is 1")
case a == 2:
fmt.Println("a is 2")
}
到目前为止,我们已经了解了构建 switch 语句的四种方法:仅使用初始值设定项、仅使用值、两者都使用或都不使用。但我们的重点主要集中在switch本身。
接下来,我们将深入探讨 case
部分如何发挥作用以及如何在代码中充分利用它。
3. 具有多个值的情况
是的,标题表明了,您可以将多个值分组在一个案例中。
这种方法可以让你的代码更简洁、更容易阅读:
switch a := 1; a {
case 1, 2, 3: // <--
fmt.Println("a is 1, 2 or 3")
}
我注意到许多 Go 新手并不知道这种功能。相反,他们可能会写这样的内容:
switch a := 1; a {
case 1:
case 2:
case 3:
fmt.Println("a is 1, 2 or 3")
}
但由于 switch
在 Go 中的工作方式,这种方法不太正确。
在此示例中,打印语句仅与最后一个案例(案例 3)链接。因此,如果 a 是 1 或 2,则不会发生任何情况,因为这些情况后面没有指令,因此程序将跳过它们。
4. 带有fallthrough关键字的案例
该关键字允许继续执行后续情况,而不检查其条件。它与大多数语言处理 switch case 的方式有点不同。
下面的示例展示了 fallthrough
的工作原理:
switch a := 1; a {
case 1:
fmt.Println("a is 1")
fallthrough
case 2:
fmt.Println("Now in case 2")
default:
fmt.Println("Neither 1 nor 2")
}
你认为输出会是什么?
在这种情况下,当 a 为 1 时,程序首先打印“a is 1”。然后,由于fallthrough关键字,它立即 fallthrough
下一个情况(情况2)而不检查a是否实际上是2。因此,它也会打印“Now in case 2”。
您仍然可以将 fallthrough
关键字放在 case 2
中,程序将继续下一个案例(默认)并打印“Neither 1 Nor 2”。
switch a := 1; a {
case 1:
fmt.Println("a is 1")
fallthrough
case 2:
fmt.Println("Now in case 2")
fallthrough
default:
fmt.Println("Neither 1 nor 2")
}
// Output:
// a is 1
// Now in case 2
// Neither 1 nor 2
请记住,Go 中的 fallthrough
关键字会绕过以下情况的条件检查。因此,它不用于 switch 语句的最终情况,因为没有后续情况可以转换到。
5. 默认情况及其细微差别
Go 的 switch 语句中的 default
情况与 if 语句中的 else 部分类似。
这是当其他情况都不匹配时运行的部分,但 Go 中的默认情况有一些有趣的地方:
尽管在大多数编程语言中 default
大小写通常位于末尾,但在 Go 中,它可以放置在 switch 语句中的任何位置。为了清楚起见,我们大多数人都把它放在最后,但让我们看看当我们把它放在开头时会发生什么:
switch a := 1; a {
default:
fmt.Println("Neither 1 nor 2")
case 1:
fmt.Println("a is 1")
case 2:
fmt.Println("Now in case 2")
}
在此示例中,即使默认情况最先出现,它仍然被视为最后的手段,仅在没有其他情况匹配时才运行。
但还有另一层需要探索。
如果我们将默认情况与fallthrough关键字混合在一起会怎么样?让我们来看看:
switch a := 3; a {
default:
fmt.Println("Neither 1 nor 2")
fallthrough
case 1:
fmt.Println("a is 1")
case 2:
fmt.Println("Now in case 2")
}
// Output:
// Neither 1 nor 2
// a is 1
在这种情况下,当 a 为 3 时,交换机以默认情况启动,打印“Neither 1 Nor 2”。然后,由于失败,它移动到下一个情况,打印“a is 1”。
6. 使用类型断言进行切换
switch 语句不仅可以处理值,还可以处理类型。这在处理接口时特别有用。
类型断言是使这成为可能的功能,它允许您检查接口值的类型并根据该类型运行不同的代码部分:
func main() {
var i interface{} = "hello"
switch v := i.(type) {
case int:
fmt.Println("i is an int and its value is", v)
case string:
fmt.Println("i is a string and its value is", v)
default:
fmt.Println("Unknown type")
}
}
在本例中, i
是存储字符串的接口变量。
switch 语句使用 i.(type)
来确定 i 的类型,然后根据该类型选择一个案例来执行:
- 它检查每种情况的特定类型(如 int 或 string)。
- 在每种情况下,v 都表示 i 的值作为在该情况下检查的类型,因此您可以像使用该类型的任何变量一样使用 v。
就这样,您现在已经掌握了 Go 中的 switch case :)