Go流程控制

4/15/2021 go

# 条件语句

if - else语句,与其他语言相似,需要注意的是,go编译器需要else ifelse两侧的}``{需要保持在同一行

if 后面跟的条件表达式,需要返回布尔类型,也是truefalse,不能是0、1或者nil,同样支持 &&||

import "fmt"

func main() {
    age := 20
    gender := "male"
    if age > 18 {
        fmt.Println("已经成年了")
    } else if age >12 {
        fmt.Println("已经是青少年了")
    } else {
        fmt.Println("还不是青少年")
    }

    // 多条件
	if age > 18 && gender == "male" {
		fmt.Println("是成年男性")
	}
    
    // 组合使用
    if age := 20; age > 18 {
        fmt.Println("已经成年了")
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 选择语句

格式如下,注意 case 表达式后的冒号

switch 表达式 {
    case 表达式1:
        代码块
    case 表达式2:
    default:
        代码块
}
1
2
3
4
5
6
7

注意:

  • switch 后面可以不接表达式,直接判定里面的case,此时逻辑类似于else if
  • switch 后面可以接函数表达式,只要函数表达式返回值于case后面的值类型保持一致
  • case 后边的表达式可以的简单表达式,多条件表达式(隔开)
  • fallthrough 穿透能力,可以返回判定下一个表达式的结果,但只能一层

常规单、多条件,fallthrough实例

func switchNoCondition() {
	score := 30
	switch {
	case score >= 95 && score <= 100:
		fmt.Println("优秀")
	case score >= 80:
		fmt.Println("良好")
	case score >= 60:
		fmt.Println("合格")
	case score >= 0:
		fmt.Println("不合格")
		fallthrough
	case score <= 30, score >= 0:
		fmt.Println("差,fallthrough 穿透了第一层")
	case score > 100:
		fmt.Println("fallthrough 穿透不了第二层")
	default:
		fmt.Println("输入有误...")
	}
}

// 不合格
// 差,fallthrough 穿透了第一层
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

switch 后面接函数表达式

func switchConditionFunc() {
	chinese := 80
	english := 50
	math := 100

	switch getResult(chinese, english, math) {
	// case 后也必须 是布尔类型
	case true:
		fmt.Println("该同学所有成绩都合格")
	case false:
		fmt.Println("该同学有挂科记录")
	}
}

func getResult(args ...int) bool {
	for _, i := range args {
		if i < 60 {
			return false
		}
	}
	return true
}

// 该同学有挂科记录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 循环语句

for 循环语句后面可以跟三种表达形式,单表达式、多表达式(类似java fori循环),range表达式(遍历可迭代的对象),还有一种没有条件的,类似于死循环

格式:

for [condition |  ( init; condition; increment ) | Range]
{
   statement(s);
}
1
2
3
4
  • 单条件
func forSingleFunc() {
	i := 0
	for i < 3 {
		fmt.Println(i)
		i++
	}
}
1
2
3
4
5
6
7
  • 多条件
func forMoreFunc() {
	for i := 0; i < 3; i++ {
		fmt.Println(i)
	}
}
1
2
3
4
5
  • for-range
func forRangeFunc() {
	myArr := [...]string{"arr1", "arr2", "arr3"}
	for _, item := range myArr {
		fmt.Printf("item is %s\n", item)
	}
}

// item is arr1
// item is arr2
// item is arr3
1
2
3
4
5
6
7
8
9
10
  • 无条件
func forNoFunc() {
	for {
    // 等价于 for ;;{
		fmt.Println("无限打印")
	}
}
1
2
3
4
5
6

# 无条件跳转语句

格式如下,goto打破原有的代码执行顺序,通常与条件语句使用实现条件转移,构成循环,跳出循环等功能,

注意:goto 标签 和 标签:表达式之前不能变量声明,否则会报语法错误

goto 标签;
...
...
标签: 表达式;
1
2
3
4

打印1-10之间的偶数

func getEvenNumberFunc() {
	i := 1
flag:
	for i <= 10 {
		if i%2 == 1 {
			i++
			goto flag
		}
		fmt.Println(i)
		i++
	}
}
1
2
3
4
5
6
7
8
9
10
11
12

# 延迟语句

格式如下:defer后面跟函数的调用即可,

defer的使用场景,对于多次资源调用的方法,最后需要关闭资源的场景,在return后会自动执行defer,避免多次手动关闭资源

defer xxxfunc()
1
  • defer只是延时函数的调用,不受后面的逻辑影响,多个defer逆序输出
func deferOrderOneFunc() {
	name := "go"
	age := 18
	defer fmt.Println(name) // 输出: go
	defer fmt.Println(age)  // 输出: 18

	name = "python"
	fmt.Println(name) // 输出: python
}

// python
// 18
// go
1
2
3
4
5
6
7
8
9
10
11
12
13
  • defer在return之后
var name = "go"

func main() {
	// defer 顺序在 return之后
	myName := deferOrderTwoFunc() 
	fmt.Printf("main 函数里的name: %s\n", name)   // 先return name被defer修改了全局变量,name是go
	fmt.Println("main 函数里的myName: ", myName)  // return 后,name被defer修改了全局变量,此时赋值给myName的是python
}

func deferOrderTwoFunc() string {
	defer func() {
		name = "python"
	}()

	fmt.Printf("deferOrderTwoFunc 函数里的name:%s\n", name) // 此时,name全局变量为go
	return name	
}

// deferOrderTwoFunc 函数里的name:go
// main 函数里的name: python
// main 函数里的myName:  go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  • defer与匿名函数
func anonymousFunc() {
	name := "go"
	defer func() {
		fmt.Println(name) // 输出: python
	}()
	defer func(name string) {
		fmt.Println(name) // 输出: go
	}(name)
	name = "python"
	fmt.Println(name) // 输出: python
}

// python
// go
// python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  • defer还可以修改返回值
func triple(x int) (result int) {   // x传值4
	defer func() {
		result += x    // defer 修改返回值 8+4
	}()
	return double(x)   // 8
}

func double(x int) int {
	return x + x      // 4 + 4 
}

// 12
1
2
3
4
5
6
7
8
9
10
11
12

# 练习源码

ProcessControl (opens new window)