第六章 玩抽签(条件分支)

条件分支,说的是“如果△△,那么〇〇”的这样的逻辑判断以后,再根据前提条件,决定走哪一条处理流程。

从这里开始,将会越来越有“编程”的味道。这次我们将通过制作抽签游戏,学习条件分支的用法。

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 相等,选择执行对应的分支。