6. 流程控制

流程控制语句用于设定程序执行的顺序,建立程序的逻辑结构,在 Go 语言中,提供了顺序,条件选择,循环控制以及跳转等流程控制。在条件选择中,包含的关键字有 if ... else ...switch。在循环控制中提供的关键字有 for ...。在跳转流程中包含的关键字有 breakcontinuegotofallthrough

6.1. 顺序执行

顺序执行是最简单的流程,顺序执行顾名思义,就是按照顺序执行,前面章节介绍的内容基本是顺序执行流程,如下代码就是一个简单的顺序执行流程:

func main() {
    fmt.Println("1")
    fmt.Println("2")
    fmt.Println("3")
}

在上述代码的执行中,分别打印“1”,“2”,“3”。

6.2. 条件选择

在 Go 语言的条件选择中提供了两类关键字,一类是 if ... else ...,另一类是switch

6.2.1. if 条件选择

if 条件选择又分为三种形式:

  • 普通的 if 语句
  • if ... else ...
  • 多重选择:if ... else if ... else ...

先看普通的 if 语句,用于判断是否满足 if 的条件,满足则执行,代码如下:

func main() {
	a := 5
	if a > 4 {
		fmt.Println("大于 4")
	}
}

由于变量 a 大于 4,满足 if 的条件,因此执行下面的语句。if ... else ... 语句中,在 else 部分提供了不满足的处理流程,代码如下:

func main() {
	a := 3
	if a > 4 {
		fmt.Println("大于 4")
	} else {
		fmt.Println("小于等于 4")
	}
}

由于此时设置的变量 a 为 3,不满足 if 的条件,满足 else,因此执行 else 下面的代码。多重选择if ... else if ... else ... 提供了更多的选择,代码如下:

func main() {
	a := 3
	if a > 4 {
		fmt.Println("大于 4")
	} else if a == 3 {
		fmt.Println("等于 3")
	} else {
		fmt.Println("小于 3")
	}
}

变量 a 为 3,满足中间 else if 的条件,因此执行这一段代码。在 Go 语言中,针对上述的代码还有简写的形式,如下:

func main() {
	if a := 3; a > 4 {
		fmt.Println("大于 4")
	} else {
		fmt.Println("小于等于 4")
	}
}

6.2.2. switch 条件选择

```switch` 是另一个条件选择语句,针对上面 if 的代码,可以切换到 switch 的格式,如下:

func main() {
	a := 3
	switch {
	case a > 4:
		fmt.Println("大于 4")
	case a == 3:
		fmt.Println("等于 3")
	default:
		fmt.Println("小于 3")
	}
}

如果熟悉其他编程语言,我们会发现在 Go 语言中,case 语句后面没有 break,这是因为 Go 语言中就默认了 break。如果我们对上面的代码稍微改一下,如下:

func main() {
	a := 3
	switch {
	case a > 4:
		fmt.Println("大于 4")
	case a == 3:
		fmt.Println("等于 3")
	default:
		fmt.Println("小于 4")
	}
}

default 部分改成如此的格式,因为 Go 语言的 case 语句默认带有 break,因此不会执行 default 部分,若要让 default 执行,需要使用 fallthrough 关键字,Go 语言中的 fallthrough 关键字在 switch 中继续执行下一个 case,代码如下:

func main() {
	a := 3
	switch {
	case a > 4:
		fmt.Println("大于 4")
	case a == 3:
		fmt.Println("等于 3")
		fallthrough
	default:
		fmt.Println("小于 4")
	}
}

6.3. for 循环

6.3.1. for 循环

for 循环在前面的章节中已经使用到,下面我们用 for 循环做一个累加,如下代码:

func main() {
	sum := 0
	for i:=1; i<50; i++ {
		sum += i
	}
	fmt.Println(sum)
}

注意:在 Go 语言中,没有 while 和 do … while 这样的循环。若要实现无限循环,可以直接用 for 循环即可,代码如下:

func main() {
	a := 0
	for {
		a += 1
		fmt.Println(a)
	}
}

我们发现代码一直会执行下去,这便实现了无限循环的功能。

6.3.2. for…range 循环

在前面章节也介绍到,对于数组、切片以及字典,可以使用 for range 遍历,代码如下:

func main() {
	a := [5]int{1, 2, 3, 4, 5}
	for index, value := range a {
		fmt.Printf("index: %d, value: %d\n", index, value)
	}
}

6.4. 跳转流程

在跳转流程中包含的关键字有 breakcontinuegotofallthrough。其中,fallthrough 在前面已经介绍到。

6.4.1. break 关键字

break 关键字用于在循环中跳出当前的循环,如下代码:

func main() {
	a := 0
	for {
		a += 1
		// 当 a == 10 时,跳出循环
		if a == 10 {
			break
		}
		fmt.Println(a)
	}
}

执行代码,我们发现,补在像上面那样,会无限执行下去,当 a == 10 时,循环便停止了,对于多层循环,break 语句只能跳出当前的循环,如下代码:

func main() {
	for i:=0; i < 10; i++ {
		for j:=0; j < 10; j++{
			if j == 5 {
				break
			}
			fmt.Println(i, j, i+j)
		}
	}
}

执行代码,我们发现,变量 j 的取值只能是 0,1,2,3,4,而变量 i 的取值则是 0 到 9,因此 break 语句只能跳出当前的循环,也就是变量 j 所在的循环。若要只跳出 j == 5 这个情况,只能使用 continue 关键字。

6.4.2. continue 关键字

continue 关键字用于在循环中跳出当前的循环,如下代码:

func main() {
	for i:=0; i < 10; i++ {
		for j:=0; j < 10; j++{
			if j == 5 {
				continue
			}
			fmt.Println(i, j, i+j)
		}
	}
}

执行代码,我们发现只是跳出了 j == 5 的情况。

6.4.3. goto 关键字

goto 关键字用于跳转到特定的位置,对于上面的代码,如果在 j == 5 时,跳出所有的代码,我们有如下的写法:

func main() {
	flag := true
	for i:=0; i < 10; i++ {
		for j:=0; j < 10; j++{
			if j == 5 {
				flag = false
				break
			}
			fmt.Println(i, j, i+j)
		}
		if !flag {
			break
		}
	}
}

通过设置 flag 标记,判断是否同时退出外层循环。这个时候就可以使用 goto 语句,直接跳转到指定位置,代码如下:

func main() {
	for i:=0; i < 10; i++ {
		for j:=0; j < 10; j++{
			if j == 5 {
				goto AllBreak
			}
			fmt.Println(i, j, i+j)
		}
	}
	AllBreak:
}

注意:跳转位置的 AllBreak 后面有 :

6.5. 本章小结

在 Go 语言中,提供了顺序,条件选择,循环控制以及跳转等流程控制。在条件选择中,包含的关键字有 if ... else ...switch。在循环控制中提供的关键字有 for ...,特别地,对于数组、切片以及字典,可以使用 for range 遍历。在跳转流程中包含的关键字有 breakcontinuegotofallthrough,其中,break 用于跳出当前循环,continue 用于跳出本次循环,goto 用于跳转到指定位置,fallthrough 用于 switch 中继续执行下面一个 case 的关键字。