第六章 玩抽签(条件分支)
条件分支,说的是“如果△△,那么〇〇”的这样的逻辑判断以后,再根据前提条件,决定走哪一条处理流程。
从这里开始,将会越来越有“编程”的味道。这次我们将通过制作抽签游戏,学习条件分支的用法。
5.1 if 语句
首先,我们来写一个简单的程序,随机决定是中奖还是没中奖。
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
if rand.N(2) == 1 { // rand.N(2) 的返回值可能是0或1
fmt.Println("您中奖了!")
} else {
fmt.Println("很遗憾,没中")
}
fmt.Println("抽奖结束")
}
由于用了随机值,所以程序的输出,在每次执行时都会变化。
$ go run .
您中奖了!
抽奖结束
$ go run .
很遗憾,没中
抽奖结束
$ go run .
很遗憾,没中
抽奖结束
if是用于进行条件分支的关键字。通过像if △△ { 〇〇 }这样写,当满足△△的条件时,仅执行{ 〇〇 }的内容。==是用来检查左右值是否相等的符号。- 通过写成
else { ×× }的形式,当不满足if △△的条件时执行{ ×× }。 - if ~ else 结束后的代码(这次是
fmt.Println("抽奖结束")),与if无关,因此始终会执行。
结果是,“如果 rand.N(2) 的返回值等于 1,则显示为中奖,如果为 0,则显示为未中奖。最后始终显示抽奖结束。”
else if
判断完一个条件,如果信息量还不足够,并希望确认另一个条件成立不成立,此时应该使用 else if 。
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
if rand.N(2) == 0 {
fmt.Println("很遗憾,没中")
} else if rand.N(2) == 0 {
fmt.Println("2等奖")
} else {
fmt.Println("1等大奖!!!")
}
}
$ go run .
很遗憾,没中
$ go run .
1等大奖!!!
$ go run .
2等奖
- 如果满足最初的条件
if rand.N(2) == 0,将只执行最初的{}里面的内容,并显示很遗憾,没中。 - 如果最初的条件未满足,会继续检查
else if rand.N(2),如果满足条件,则显示2等奖。 - 如果第二个条件也没有满足,则执行最后的
{}的内容,并显示1等大奖!!!。
布尔值
if △△ 的“△△”中,对应的内容称为布尔值(英文为布尔/boolean,简称布尔/bool)。布尔值是只有真/true 或假/false 两个选项的特殊值。
普通数字可以是 0, 1, 2, 3...等无限多,但布尔值只有“真”和“假”这两种。
if △△ { 〇〇 } else { ×× } 这个语句,指**“如果△△的真布尔值为真,则执行〇〇;如果为假,则执行××”**。
然后, == 是一个求真值的符号,如果左右的值相等,整个式子则为 true ,如果不相等整个式子为 false 。
还有其他的求真值的符号,如 > (大于)、 && (且)、 || (或者)等多种。这些可以组合在一起进行判断。我们会在需要的时候再讨论这些。
[面向有经验的人] Go 不能使用其他类型代替布尔值
Go 不能将用“布尔值”以外的类型代替布尔值。例如,在 C 语言中,0 代表假,其他值被视为真。
但在 Go 中,0 不能用来代替布尔值。必须使用逻辑运算符将其转换为布尔值。
5.2 switch语句
控制条件分支,除了 if 语句以外,也可以使用 switch 语句。 switch 在需要判断多个条件时非常方便。
switch 有几种语法,最基本的模式是“根据 switch 后面的值与哪个 case 相等,进行分支判断”。
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
switch rand.N(3) {
case 0:
fmt.Println("是0")
case 1:
fmt.Println("是1")
default:
fmt.Println("其他数字")
}
}
运行结果示例:
$ go run .
是1
$ go run .
其他数字
$ go run .
是1
$ go run .
是0
当 switch 后面的值与某个 case 匹配时,将执行 case 的内容。
如果与任何 case 都不匹配,将执行 default 。
[面向有经验的人] go 的 switch 不需要 break 语句
与 C 语言等不同,Go在每个 case 的末尾不需要写 break ,而是默认可以直接跳出 switch 语句,不进入下一个 case 。
用 case 合并分支
在 Go 中,可以通过在 case 后面用逗号分隔,列出多个值来合并 case。
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
switch rand.N(3) {
case 0, 1:
fmt.Println("是0或1")
default:
fmt.Println("其他数字")
}
}
$ go run .
是0或1
$ go run .
其他数字
$ go run .
是0或1
$ go run .
其他数字
用 switch 来代替 else if
此外,Go 语言还有一种特有的语法,即在 case 后面写条件而不是值。
func main() {
switch { // 这种写法里面,switch后面没有值
case rand.N(2) == 0:
fmt.Println("没中")
case rand.N(2) == 0:
fmt.Println("3等奖!")
case rand.N(2) == 0:
fmt.Println("2等奖!")
default:
fmt.Println("1等大奖!")
}
}
上述内容用 else if 重写,会变成这样的程序。两者的意思相同。请使用您喜欢的方式。
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
if rand.N(2) == 0 {
fmt.Println("没中")
} else if rand.N(2) == 0 {
fmt.Println("3等奖!")
} else if rand.N(2) == 0 {
fmt.Println("2等奖!")
} else {
fmt.Println("1等大奖!")
}
}
5.3 制作抽签程序
那么,利用这些知识,让我们做一个抽签游戏吧。
从 0 到 4 的 5 个值中抽取一个,将其与运势对应。
| 数字 | 运势 |
|---|---|
| 4 | 大吉 |
| 3 | 吉 |
| 2 | 中吉 |
| 1 | 凶 |
| 0 | 大凶 |
那么,程序会变成什么样呢?以下是示例答案:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
switch rand.N(5) {
case 4:
fmt.Println("大吉")
case 3:
fmt.Println("吉")
case 2:
fmt.Println("中吉")
case 1:
fmt.Println("凶")
case 0:
fmt.Println("大凶")
}
}
改变概率
上面的程序,从大吉到大凶,出现概率都是一样的,但这不太像抽签。我们来根据运势,改变出现的概率。做法有很多,这次我们简单地将一个运势,对应多个数字。
| 数字 | 运势 |
|---|---|
| 9 | 大吉 |
| 8, 7, 6 | 吉 |
| 5, 4, 3 | 中吉 |
| 2, 1 | 凶 |
| 0 | 大凶 |
这样做,“吉”的出现概率将会是“大吉”的3倍。那么,写成程序会是怎样呢?
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
switch rand.N(10) {
case 9:
fmt.Println("大吉")
case 8, 7, 6:
fmt.Println("吉")
case 5, 4, 3:
fmt.Println("中吉")
case 2, 1:
fmt.Println("凶")
case 0:
fmt.Println("大凶")
}
}
将多个 case 汇总在一起,可以写得更简洁。
本章总结
- if △△ { 〇〇 } else { ×× }` 这个句子的意思,是“如果△△的布尔值为真,则执行〇〇;如果为假,则执行××。”
switch在需要区分多个条件时非常方便。根据switch后面的值与哪个case相等,选择执行对应的分支。