<Go>2 程序流程控制

本文最后更新于:2023年6月27日 上午

2 程序流程控制

2.1 运算符

运算符是一种特殊的符号,用以表示数据运算、赋值、比较等

主要有 6 类:

  • 算术运算符:++、--、+、-、*、/
  • 赋值运算符:=、+=、-=、&=、|=、^=、!=
  • 比较运算符 / 关系运算符:>、<、<=、>=、==、!=
  • 逻辑运算符:&&、||
  • 位运算符:>>、<<、>>>、&、^、!、|
  • 其他运算符:取址符 &、指针符 *

特别地:Go 中的 ++-- 都只能独立使用,且只能出现在变量后侧:

var i int = 10
i++
/* --i */					// 错误用法
/* var n int = i++ */		// 错误用法

另外,Go 语言明确不支持三元运算符

2.2 键盘输入、屏幕输出

这两个功能包含在 fmt 包中。

导入 fmt 包:

import "fmt"

#屏幕输出:

  • fmt.Print(a... interface{}):输出该语句

    fmt.Println(a... interface{}):输出该语句,之后换行

    fmt.Printf(format string, a... interface{}):格式化输出语句

#键盘输入:

  • fmt.Scanln(a... interface{}):获取输入,保存到传入参数中。直到换行时才停止扫描

    fmt.Scanf(format string, a... interface{}):根据指定格式,将成功读取的空白分割的值保存到传入参数中

2.3 程序流程控制

程序流程控制主要分为三种

  • 顺序控制
  • 分支控制
  • 循环控制

2.3.1 顺序控制

程序从上到下逐行执行,中间没有任何判断和跳转(默认的控制顺序)

graph LR
A(A语句)-->B(B语句)-->C(C语句)-->D(D语句)-->E(...)

2.3.2 分支控制

#单分支控制:

当条件满足时,执行表达式。

graph LR
A(if 语句)--> B{条件表达式}
B --true--> C(执行语句块)
C --> D(继续)
B --false----> D

**注意:**在 Go 中,条件表达式不能加括号,且结构体即使只有一句也必须加上大括号

if i := 5; i < 10 {
    i++
}

#双分支控制:

当条件满足时,执行表达式。否则执行另一表达式

graph LR
A(if...else 语句)--> B{条件表达式}
B --true--> C(执行语句块1)
C --> D(继续)
B --false--> F(执行语句块2)
F --> D

**注意:**在 Go 中,不能让 else 语句另起一行

if i < 10 {
    i++
} else {
    i--
}

#多分支控制:

有条件满足时,执行该表达式。否则执行 else 语句或直接继续

graph LR
A(if...else if  语句)--> B{条件1}
B --true--> C(执行语句块1)
C --> D(继续)
B --false--> F{条件2}
F --true--> G(执行语句块2)
G --> D
F --false--> H{条件3}
H --true--> I(执行语句块3)
I --> D
H --false--> J(else 语句块)
J --> D

其中,else 语句块不是必须的。

if i < 10 {
    i++
} else if i > 20 {
    i--
} else {
    i = 0
}

#switch 分支结构:

switch 语句用于基于不同条件执行不同动作。

每个 case 分支都是唯一的,从上到下逐一测试,直到匹配为止。

graph LR
A(switch  语句)--> B{表达式 a}
B -->b1[a == 表达式 1]--true--> C(语句块1)
b1 --false-->b2[a == 表达式 2]--true--> D(语句块2)
b2 --false-->b3[a == 表达式 3]--true--> E(语句块3)
b3--false--> F(default语句块)
C --> G(继续)
D --> G
E --> G
F --> G
C -.fallthrough.-> D
D -.fallthrough.-> E
E -.fallthrough.-> F
var i int
fmt.Scanln(&i)
switch i {
    case 1, 4, 2 << 3:
    	fmt.Println("喵喵喵")
    case 2:
    	fmt.Println("汪汪汪")
    case 3:
    	fmt.Println("嗷嗷嗷")
    default:
    	fmt.Println("滋滋滋")
}

注意事项:

  • case 后可以是一个表达式(常量、变量、有返回值的函数)

  • case 后各个表达式数据类型需和 switch 表达式数据类型一致

  • case 后可以有多个表达式,以 , 分隔

  • case 后的表达式若是常量值,则要求不能重复

  • case 后不需要加 break,default 语句可以省略

  • switch 后面可以不带表达式,此时 case 表达式数据类型是布尔值。类似于多个 if…else 分支使用

  • (不推荐)switch 后可以直接声明 / 定义一个变量,并以 ; 结束

  • 在 case 语句块添加 fallthrough,则会穿透执行下一个 case 语句块

  • type switch 可以用于判断某个 interface 的变量类型

    switch i := x.(type) {
        case int:
        	fmt.Println("是 int 类型")
        case bool:
        	fmt.Println("是 bool 类型")
    }
  • 在 case 语句块添加 fallthrough,则会穿透执行下一个 case 语句块

    switch i := 2; i {
    case 1:
    case 2:
        fallthrough
    case 3:
    }

    fallthrough 必须出现在 case 块的最后,且该 case 块不能是最后一个 case 块

    不允许在 type switch 中使用 fallthrough

2.3.3 循环控制

基本语法:

for 循环变量初始化; 循环条件; 循环变量迭代 {
    循环操作
}
graph LR
A(for 循环语句) --> F[循环变量初始化] --> B{循环条件} --false--> D(继续)
B --true--> C(循环操作)  --> E[循环变量迭代]  --> B

for 循环四个要素:循环变量初始化、循环的条件、循环的操作、循环变量迭代

所有循环开始前仅一次进行初始化。直到循环条件变为 false 前,执行循环操作。每轮循环结束后,进行循环变量迭代。

可以把 变量初始化 和 循环变量迭代 写在其他位置。循环条件为空时,默认无限循环

#for-range

Golang 提供 for-range 方式,以便于遍历字符串和数组

var str string = "辟邪剑法"
for index, val := range str {				// index 即下标,val 即值。使用 _ 忽略其中的一个
    fmt.Printf("%d\t%c\n", index, val)
}

汉字占 3 字节。传统方法遍历字符串时,可能产生乱码。但 for-range 方式遍历时不会出错。

#while 和 do…while

Go 语言中没有 while 和 do…while 语法。通过 for 循环来模拟实现其效果。

/* 模拟 while */
for {
    if (循环条件表达式) {
        break;
    }
    循环操作
    循环变量迭代
}

/* 模拟 do...while */
for {
    循环操作
    循环变量迭代
    if (循环条件表达式) {
        break;
    }
}

2.4 跳转控制语句

#break

用于中止一个语句块的执行。用于中断当前 for 循环或跳出 switch 语句

graph LR
A(for 语句) --初始化--> B{循环条件} --false--> D(继续)
B --true--> c1(语句1) --> c2(语句2) --> c3(语句3) --> E[循环变量迭代] --> B
c1 --break--> D
  • break 默认会跳出最近的循环

  • break 语句出现在多层嵌套语句块中时,能通过标签指明要中止哪一层语句块

    lable1:								// 标签
    for {
        for {
            fmt.Print("免疫 ")
            i++
            if i >= 100 {
                break lable1
            } else if i%10 == 0 {
                break
            }
        }
        fmt.Println()
    }

#continue

在循环中出现。用于结束本次循环,继续下一次循环

graph LR
A(for 语句) --初始化--> B{循环条件} --false--> D(继续)
B --true--> c1(语句1) --> c2(语句2) --> c3(语句3) --> E[循环变量迭代] --> B
c1 --continue--> E
  • continue 默认会跳过最近的循环
  • continue 语句出现在多层嵌套语句块中时,能通过标签指明要跳过哪一层循环

#goto

可以无条件地转移到程序中指定的行

  • goto 语句通常与条件语句配合使用,以实现条件转移,跳出循环体等功能。
  • 一般不建议使用 goto 语句,以免造成流程混乱

#return

用于方法或函数中。表示跳出所在的方法或函数

graph LR
    A(调用方法A) --> B(语句a)
    subgraph 方法A
		B --> C(语句b) --> D(语句c) --> E(语句d)
    end
E --执行完毕--> F(继续)
C --return--> F

如若写在主方法,会直接跳出程序


<Go>2 程序流程控制
https://i-melody.github.io/2022/06/07/Go/2 程序流程控制/
作者
Melody
发布于
2022年6月7日
许可协议