如何用 Go 编写开关语句

介绍

条件声明使程序员能够指导他们的程序采取某些行动,如果一个条件是真实的,另一个行动,如果条件是错误的。 通常,我们想要比较一些 变量与多个可能的值,在每个情况下采取不同的行动。 可以使用单独的 if声明来完成这项工作。 但是,编写软件不仅仅是让事情工作,而且还可以将你的意图传达给你的未来自我和其他开发人员。

在本教程中,我们将看看开关语句能做些什么的几个例子,它所取代的如果语句,以及它最适宜应用的地方。

交换声明的结构

Switch 通常用于描述一个程序在给变量分配特定值时所采取的操作. 下面的示例展示了我们如何使用如果陈述来实现这一点:

 1package main
 2
 3import "fmt"
 4
 5func main() {
 6    flavors := []string{"chocolate", "vanilla", "strawberry", "banana"}
 7
 8    for _, flav := range flavors {
 9    	if flav == "strawberry" {
10    		fmt.Println(flav, "is my favorite!")
11    		continue
12    	}
13
14    	if flav == "vanilla" {
15    		fmt.Println(flav, "is great!")
16    		continue
17    	}
18
19    	if flav == "chocolate" {
20    		fmt.Println(flav, "is great!")
21    		continue
22    	}
23
24    	fmt.Println("I've never tried", flav, "before")
25    }
26}

这将产生以下产出:

1[secondary_label Output]
2chocolate is great!
3vanilla is great!
4strawberry is my favorite!
5I've never tried banana before

中,我们定义了冰淇淋味道的 Slic。然后我们使用一个 ‘for loop’来迭代它们。我们使用三个如果语句来打印不同的信息,说明不同冰淇淋味道的偏好。

随着我们添加新的冰淇淋偏好,我们必须不断添加如果陈述来处理新案例。 重复的消息,如瓦尼拉巧克力的情况,必须有重复的如果陈述。 对于我们代码的未来的读者(包括我们),如果陈述的重复性掩盖了他们所做的事情的重要部分 – 将变量与多个值进行比较并采取不同的行动。

交换语句始于交换关键字,并以最基本的形式随之以某些变量进行比较,随之以一对弯曲的条款(`{})来进行比较,其中可以出现多个 _case 条款。 Case 条款描述了您的 Go 程序应该采取的行动,当交换语句中提供的变量等于案例条款所指的值。

 1package main
 2
 3import "fmt"
 4
 5func main() {
 6    flavors := []string{"chocolate", "vanilla", "strawberry", "banana"}
 7
 8    for _, flav := range flavors {
 9    	switch flav {
10    	case "strawberry":
11    		fmt.Println(flav, "is my favorite!")
12    	case "vanilla", "chocolate":
13    		fmt.Println(flav, "is great!")
14    	default:
15    		fmt.Println("I've never tried", flav, "before")
16    	}
17    }
18}

结果与以前相同:

1[secondary_label Output]
2chocolate is great!
3vanilla is great!
4strawberry is my favorite!
5I've never tried banana before

我们再次在中定义了冰淇淋味的片段,并使用范围声明重复每个味道,但这次我们使用了一个交换声明,将检查味道变量。我们使用两种案例声明来表示偏好。我们不再需要继续声明,因为只有一个案例声明将由交换声明执行。我们还能够将巧克力瓦尼拉条件的重复逻辑结合起来,通过在案例声明中的每个声明中分开一个号。默认声明将作为我们的捕捉声明。它将为我们在交换声明体内未考虑过的任何口味运行。在这种情况下,香蕉将导致缺陷试图禁止打印,我从未

这种简化形式的交换陈述解决了最常见的用途:比较一个变量与多个替代方案. 它也为我们提供了便利,在我们想要采取相同的行动为多个不同的值和一些其他行动时,没有列出的条件通过使用提供的默认关键字满足。

当这种简化形式的交换机被证明过于限制时,我们可以使用更一般的形式的交换机陈述。

通用Switch声明

交换语句对组合更复杂的条件符的集合有用,以表明它们是以某种方式相关的。这在比较某些变量与一系列值时最常见,而不是像在上一个示例中那样对特定值进行比较。

 1package main
 2
 3import (
 4    "fmt"
 5    "math/rand"
 6    "time"
 7)
 8
 9func main() {
10    rand.Seed(time.Now().UnixNano())
11    target := rand.Intn(100)
12
13    for {
14    	var guess int
15    	fmt.Print("Enter a guess: ")
16    	_, err := fmt.Scanf("%d", &guess)
17    	if err != nil {
18    		fmt.Println("Invalid guess: err:", err)
19    		continue
20    	}
21
22    	if guess > target {
23    		fmt.Println("Too high!")
24    		continue
25    	}
26
27    	if guess < target {
28    		fmt.Println("Too low!")
29    		continue
30    	}
31
32    	fmt.Println("You win!")
33    	break
34    }
35}

输出将取决于所选的随机号码以及您如何发挥游戏。

1[secondary_label Output]
2Enter a guess: 10
3Too low!
4Enter a guess: 15
5Too low!
6Enter a guess: 18
7Too high!
8Enter a guess: 17
9You win!

我們的猜測遊戲需要一個隨機數字來比較猜測,所以我們使用「rand.Intn」函數來自「math/rand」套件. 為了確保我們每次玩遊戲都會得到不同的「目標」值,我們使用「rand.Seed」來隨機計算隨機數字生成器,根據當前的時間。

fmt.Scanf函数为我们提供了读取用户输入到我们所选择的变量的一种方式。它需要一个格式字符串词汇,将用户的输入转换为我们所期望的类型。 %d’在这里意味着我们期望一个 int,我们传递了 guess变量的地址,以便fmt.Scanf能够设置该变量。 [处理任何解析错误](https://andsky.com/tech/tutorials/handling-errors-in-go)后,我们使用两个if陈述来比较用户的猜测到target` 值。

这些如果陈述掩盖了该变量被比较的值范围以某种方式相关的事实,也可以很难在一眼里说出我们是否错过了该范围的某些部分。

 1package main
 2
 3import (
 4    "fmt"
 5    "math/rand"
 6)
 7
 8func main() {
 9    target := rand.Intn(100)
10
11    for {
12    	var guess int
13    	fmt.Print("Enter a guess: ")
14    	_, err := fmt.Scanf("%d", &guess)
15    	if err != nil {
16    		fmt.Println("Invalid guess: err:", err)
17    		continue
18    	}
19
20    	switch {
21    	case guess > target:
22    		fmt.Println("Too high!")
23    	case guess < target:
24    		fmt.Println("Too low!")
25    	default:
26    		fmt.Println("You win!")
27    		return
28    	}
29    }
30}

这将产生类似于以下的输出:

1[secondary_label Output]
2Enter a guess: 25
3Too low!
4Enter a guess: 28
5Too high!
6Enter a guess: 27
7You win!

在这个版本的猜测游戏中,我们将如果陈述的块替换为交换陈述。我们将表达式参数放弃为交换,因为我们只感兴趣使用交换来收集条件。每个案例条款包含一个不同的表达式,将假设目标进行比较。类似于我们第一次将如果陈述替换为交换,我们不再需要继续陈述,因为只会执行一个案例条款。

在迄今为止我们所看到的例子中,将执行一个具体的案例陈述,偶尔,您可能希望结合多个案例条款的行为。

落后

有时你会想要重复使用另一个案例条款所包含的代码。在这些情况下,可以要求Go运行下一个案例条款的身体,使用落后关键字。

 1package main
 2
 3import "fmt"
 4
 5func main() {
 6    flavors := []string{"chocolate", "vanilla", "strawberry", "banana"}
 7
 8    for _, flav := range flavors {
 9    	switch flav {
10    	case "strawberry":
11    		fmt.Println(flav, "is my favorite!")
12    		fallthrough
13    	case "vanilla", "chocolate":
14    		fmt.Println(flav, "is great!")
15    	default:
16    		fmt.Println("I've never tried", flav, "before")
17    	}
18    }
19}

我们会看到这个结果:

1[secondary_label Output]
2chocolate is great!
3vanilla is great!
4strawberry is my favorite!
5strawberry is great!
6I've never tried banana before

正如我们之前所看到的那样,我们定义了一段字符串来表示味道,并通过这个循环重复使用for循环。这里的交换陈述与我们之前所看到的相同,但随着fallthrough关键字在case条款的末尾添加到casestrawberry。这将导致Go运行casebody,首先打印strawberry是我的最爱!字符串。当它遇到fallthrough,它将运行下一个case条款的身体。

fallthrough 关键字不常被 Go 开发人员使用,通常使用 fallthrough 实现的代码重复使用可以通过定义一个函数来更好地获得。

结论

交换声明有助于我们向其他开发人员传达,我们阅读我们的代码,一组比较是以某种方式相互相关的。它们使在未来添加新案例时更容易添加不同的行为,并使它能够确保我们忘记的任何事情都得到正确的处理以及默认条款。

如果您想了解更多关于 Go 编程语言的信息,请查看整个 How To Code in Go 系列

Published At
Categories with 技术
Tagged with
comments powered by Disqus