流程控制

教程地址:点击去往视频教程open in new window

1. if

在Go语言中,关键字if是用于测试某个条件(布尔型或逻辑型)的语句,如果该条件成立,则会执行 if 后由大括号{}括起来的代码块,否则就忽略该代码块继续执行后续的代码。

if condition {
    // 条件为真执行
}
1
2
3

condition 称之为条件表达式或者布尔表达式,执行结果需返回true或false

例子:

func main() {
	var v int = 700
	//v < 1000 这是条件表达式
	if v < 1000 {
		//为true 执行这条语句 false则不执行
		fmt.Printf("v is less than 1000\n")
	}
	fmt.Printf("Value of v is : %d\n", v)
}
1
2
3
4
5
6
7
8
9

如果条件为false,我们想要执行其他逻辑,应该怎么做呢?

可以用以下语法:

if condition {
    // true执行此代码块
} else {
    // false执行此代码块
}
1
2
3
4
5

例子:

func main() {
	var v int = 700
	//v < 1000 这是条件表达式
	if v < 1000 {
		//为true 执行这条语句 false则不执行
		fmt.Printf("v is less than 1000\n")
	} else {
		//false执行这条语句
		fmt.Printf("v is greater than 1000\n")
	}
}
1
2
3
4
5
6
7
8
9
10
11

if语句可以无限嵌套(当然实际开发过程中,并不建议嵌套过多):

func main() {
	var hp = 0
	var name = "mszlu"
	if name == "mszlu" {
		if hp <= 0 {
			fmt.Println("name为mszlu的玩家以及dead")
		}
	}
}
1
2
3
4
5
6
7
8
9

如果条件分支很多,我们可以使用以下语法:

if condition1 {
    // condition1 满足 执行
} else if condition2 {
    // condition1 不满足 condition2满足 执行
}
...
else {
    // condition1和condition2都不满足 执行
}
1
2
3
4
5
6
7
8
9

注意else if没有数量限制,同样实际编程中,并不建议有过多的分支。

例子:

func main() {
	var hp = 0
	if hp > 100 {
		fmt.Println("玩家很健康")
	}else if hp > 50 {
		fmt.Println("玩家快没血了")
	}else if hp > 10 {
		fmt.Println("玩家快死了")
	}else {
		fmt.Println("玩家死了")
	}
}
1
2
3
4
5
6
7
8
9
10
11
12

一个特殊写法:

if a := 10; a >5 {
    fmt.Println(a)
    return
}
1
2
3
4

这种写法将a的作用范围限制在if表达式中,在编程中,限制变量的作用范围对代码的稳定性有很大的帮助,因为作用范围越小,造成的影响也越小。

2. for

go语言中的循环语句只支持 for 关键字,这个其他语言是不同的。

for有很多种写法:

  • 第一种写法
sum := 0
//i := 0; 赋初值,i<10 循环条件 如果为真就继续执行 ;i++ 后置执行 执行后继续循环
for i := 0; i < 10; i++ {
    sum += i
}
1
2
3
4
5
  • 第二种写法

    //无限循环
    for{
        //无限循环代码块
    }
    
    1
    2
    3
    4
  • 第三种写法

    func main() {
    	n := 0
        //for后面只加条件 
    	for n < 3 {
    		n++
    	}
    	fmt.Println(n)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
  • 第四种写法

    func main() {
    	var slice []int = []int{1, 2, 3, 4, 5}
        //for range循环切片或数组
    	for index, value := range slice {
    		fmt.Printf("index:%d,value:%d \n", index, value)
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
  • 第五种写法

    func main() {
        //可以循环字符串 字符串底层为一个byte切片
        //字符串大小为16字节,其有一个指针和int型长度组成
    	for i, j := range "mszlu" {
    		fmt.Printf("The index number of %c is %d\n", j, i)
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
  • 第六种写法

    func main() {
        //循环map
    	mmap := map[int]string{
    		22: "mszlu",
    		33: "com",
    		44: "learn go",
    	}
    	for key, value := range mmap {
    		fmt.Println(key, value)
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  • 第七种写法

    func main() {
        //循环channel
    	chnl := make(chan int)
    	go func() {
    		chnl <- 100
    		chnl <- 1000
    		chnl <- 10000
    		chnl <- 100000
    		close(chnl)
    	}()
    	for i := range chnl {
    		fmt.Println(i)
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    结束循环有几种方式:

    • 第一种

      func main() {
      	step := 2
      	for step > 0 {
      		step--
      		fmt.Println(step)
      		//执行一次就结束了
      		return
      	}
      	//不会执行
      	fmt.Println("结束之后的语句....")
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
    • 第二种

      func main() {
      	step := 2
      	for step > 0 {
      		step--
      		fmt.Println(step)
      		//跳出循环,还会继续执行循环外的语句
      		break
      	}
      	//会执行
      	fmt.Println("结束之后的语句....")
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
    • 第三种

      func main() {
      	step := 2
      	for step > 0 {
      		step--
      		fmt.Println(step)
      		//报错了,直接结束
      		panic("出错了")
      	}
      	//不会执行
      	fmt.Println("结束之后的语句....")
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
    • 第四种

      func main() {
      	for x := 0; x < 10; x++ {
      		if x == 2 {
      			// 跳转到标签
      			goto breakHere
      		}
      	}
      	// 手动返回, 避免执行进入标签
      	return
      	// 标签
      breakHere:
      	fmt.Println("done")
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13

    for range1.22版本有更新

func main() {
	var slice []int = []int{1, 2, 3, 4, 5}
	for index, value := range slice {
		go func() {
            //1.22版本这里会输出 1,2,3,4,5顺序不一定
            //1.22版本以前 大概率会都输出5
            //这里原因是1.22版本每次循环 index,value会创建新的变量,而不是共享变量了
			fmt.Printf("index:%d,value:%d \n", index, value)
		}()
	}
	for {
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
func main() {
    //go1.22版本 支持整型的循环
    //注意更新IDE版本,比如goland需要安装新版
	for i := range 10 {
		fmt.Println(i)
	}
}
1
2
3
4
5
6
7

3. switch

switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。

switch 分支表达式可以是任意类型,不限于常量。可省略 break,默认自动终止。

switch 语句的语法如下:

switch var1 {
    case val1:
        ...
    case val2:
        ...
    default:
        ...
}
1
2
3
4
5
6
7
8

变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值

类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。

您可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3。

例子:

func main() {
	/* 定义局部变量 */
	var grade string = "B"
	var score int = 90

	switch score {
	case 90:
		grade = "A"
	case 80:
		grade = "B"
	case 50, 60, 70:
		grade = "C"
	default:
		grade = "D"
	}
	//switch后面如果没有条件表达式,则会对true进行匹配
	switch {
	case grade == "A":
		fmt.Printf("优秀!\n")
	case grade == "B", grade == "C":
		fmt.Printf("良好\n")
	case grade == "D":
		fmt.Printf("及格\n")
	case grade == "F":
		fmt.Printf("不及格\n")
	default:
		fmt.Printf("差\n")
	}
	fmt.Printf("你的等级是 %s\n", grade)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

Go里面switch默认相当于每个case最后带有break,匹配成功后不会自动向下执行其他case,而是跳出整个switch, 那么如何做到执行完一个case之后,进入下一个case而不是跳出swtich呢?

答案是:fallthrough

func main() {
	var s = "hello"
	switch {
	case s == "hello":
		fmt.Println("hello")
		fallthrough
	case s != "world":
		fmt.Println("world")
	}
}
1
2
3
4
5
6
7
8
9
10

注意事项:

  1. 加了fallthrough后,会直接运行【紧跟的后一个】case或default语句,不论条件是否满足都会执行
func main() {
	var s = "hello"
	switch {
	case s == "hello":
		fmt.Println("hello")
		fallthrough
	case s == "world":
		fmt.Println("world")
	}
}
1
2
3
4
5
6
7
8
9
10

4. goto

goto 语句通过标签进行代码间的无条件跳转,同时 goto 语句在快速跳出循环、避免重复退出上也有一定的帮助,使用 goto 语句能简化一些代码的实现过程。

func main() {
	if 20 > 10 {
		goto GotoTag1
	}
	return
GotoTag1:
	fmt.Println("tag1")
	if 10 > 5 {
		goto GotoTag2
	}
	return
GotoTag2:
	fmt.Println("tag2")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

5. break

break 语句可以结束 for、switch 和 select 的代码块,另外 break 语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的 forswitchselect 的代码块上。

package main
import "fmt"
func main() {
OuterLoop:
    for i := 0; i < 2; i++ {
        for j := 0; j < 5; j++ {
            switch j {
            case 2:
                fmt.Println(i, j)
                break OuterLoop
            case 3:
                fmt.Println(i, j)
                break OuterLoop
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

6. continue

continue 语句可以结束当前循环,开始下一次的循环迭代过程,仅限在 for 循环内使用,在 continue 语句后添加标签时,表示开始标签对应的循环

package main
import "fmt"
func main() {
OuterLoop:
    for i := 0; i < 2; i++ {
        for j := 0; j < 5; j++ {
            switch j {
            case 2:
                fmt.Println(i, j)
                continue OuterLoop
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14