# if else (条件判断)
Go的if else写法跟Java和C等语言的方式有点区别,就是表达式不需要使用()括起来
if else 条件判断格式如下:
if 表达式1 {
分支1
} else if 表达式2 {
分支2
} else {
分支3
}
2
3
4
5
6
7
- 当表达式1的结果为 true 时,会执行分支1的代码;
- 当表达式1的结果为 false 时,会执行表达式2,若结果为 true, 则会执行分支2的代码。
- 当前面的条件都不满足,即都为 false 时,会执行分支3的代码。
package main
import "fmt"
func main() {
num := 2
if num == 1 {
fmt.Println("等于1")
} else if num < 3 {
fmt.Println("小于3")
} else {
fmt.Println(num)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
代码输出:
小于3
表达式2、分支2 、分支3都是可选的,可以根据实际情况自行选择if、if else、if else if ... else的方式
注意:Go 语言中规定:if 的 左括号 { 必须与 if 表达式放在同一行,如果强行放置在其他位置,会发生如下编译错误。
unexpected newline, expecting { after if clause
# if 的特殊写法
if 还有种特殊写法,我们可以在 if 表达式之前添加一个执行语句,再根据变量进行判断,代码如下:
package main
import "fmt"
//创建一个返回int类型为1的函数
func getRes() int {
return 1
}
func main() {
//先赋值再判断
if num := getRes(); num != 0 {
fmt.Println(num)
return
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
代码输出:
1

getRes() 是一个带有返回值的函数,它,num := getRes() 是一个语句,执行 getRes() 函数后,将返回值赋值给 num 变量。
num != 0 是 if 的条件判断表达式,当 num不为0时,打印num并返回。
这种写法可以将返回值和判断放在一行进行处理,使得返回值的作用域范围被限制在了 if else 语句组合中,这样做的好处是,变量的作用域范围越小,那么它可能造成的问题的可能性越小,这对代码的稳定性很有帮助,另外,也可以做炫技(装逼)使用。
# for(循环)
Go跟大部分语言一样,循环需要使用关键字 for 来完成,格式如下:
for 初始语句;条件表达式;末尾循环体 {
循环体代码
}
2
3
初始语句:初始语句是第一次执行循环前执行的语句,通常情况下,我们会通过它来执行变量初始化操作。注意: 通过初始语句声明的变量,作用域局限在
for循环内条件表达式:每次在循环前,会计算条件表达式的值,如果结果为
true, 则继续循环;否则将结束循环。注意:条件表达式同样可以忽略不写,若不写,由于没有终止条件,则会陷入无限死循环,导致内存溢出末尾循环体:一般为赋值表达式,给控制变量增量或减量。每次执行完
{}中的代码后执行。
执行过程:
先对初始语句赋初值;
判别初始语句 是否满足给定 条件表达式的条件,若其值为真,满足循环条件,则执行循环体内语句,然后执行 末尾循环体,进入第二次循环,再判别 条件表达式;否则判断 条件表达式 的值为假,不满足条件,就终止
for循环,执行循环体外语句。
不支持 while 和 do-while 结构
# 循环控制语句
循环执行过程中,如果需要跳过本次循环到下一次循环,可以使用continue关键字跳过本次循环,若循环被 break 、goto 、return 、panic 等语句强制退出,执行循环体外的语句。
package main
import "fmt"
func main() {
for i := 0; i < 10;i++ {
//如果i==2,跳过本次循环
if i == 2 {
continue
}
//如果i==8,终止循环
if i == 8 {
break
}
fmt.Println(i)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
代码输出:
0
1
3
4
5
6
7
2
3
4
5
6
7
# 无限循环(死循环)
语法很简单,就是初始语句、条件表达式、末尾循环体都不写:
for {
//循环体代码,会一直执行
}
2
3
# for range (键值循环)
for range 通常来遍历数组 、切片 、字符串 、map 以及通道(channel)。
# 遍历数组、切片、字符串
通过 for range 遍历数组、切片、字符串的返回值都有一个规律:
- 下标索引 index,即接收的第一个变量,变量名不一定是index,可自定义;
- 下标对应的值 value,即接收的第二个变量,变量名不一定是value,可自定义;
# 遍历切片,数组
package main
import "fmt"
func main() {
// 初始化一个切片
slice := []int{1, 2, 3, 4}
// 通过 for range 循环切片
for index, value := range slice {
fmt.Printf("index: %d, value: %d\n", index, value)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
代码输出:
index: 0, value: 1
index: 1, value: 2
index: 2, value: 3
index: 3, value: 4
2
3
4
# 遍历字符串
package main
import "fmt"
func main() {
str := "abcd"
for index, value := range str {
fmt.Printf("index: %d, value: 0x%x\n", index, value)
}
}
2
3
4
5
6
7
8
9
10
代码输出:
index: 0, value: 0x61
index: 1, value: 0x62
index: 2, value: 0x63
index: 3, value: 0x64
2
3
4
上面代码中的 value 变量实际类型是 runne, 本质上是 int32, 以十六进制格式打印出来的是字符串编码。
# 遍历 map 字典
通过 for range 遍历 map 字典会返回键和值,称为键值对,它们总是一对一出现
- 字典的key,即接收的第一个变量,变量名不一定是key,可自定义;
- 字典的key对应的值 value,即接收的第二个变量,变量名不一定是value,可自定义;
package main
import "fmt"
func main() {
m := map[int]string{
1: "haha",
2: "哈哈",
}
for key, value := range m {
fmt.Printf("key: %d, value: %s\n", key, value)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
代码输出:
key: 1, value: haha
key: 2, value: 哈哈
2
注意: 对 map 字典进行遍历时,遍历出的键值对是无序的,如果需要有序输出,需要先排序。
# 遍历通道(channel)
遍历通道(channel)有点不同,此时只会输出一个值,即管道内的类型对应的数据。
package main
import "fmt"
func main() {
// 初始化一个通道
c := make(chan int)
// 启动一个 goroutine, 功能是往通道中推送数据 1、2、3,然后关闭通道
go func() {
c <- 1
c <- 2
c <- 3
close(c)
}()
for value := range c {
fmt.Println(value)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
代码输出:
1
2
3
2
3
# 使用匿名变量
什么是匿名变量?
- 1、它可以理解成一种占位符,用下划线
_表示; - 2、这种变量不会分配内存,也不会占用变量名;
- 3、在
for range中,可以通过匿名变量接受键 key,也可以接受值 value。
package main
import "fmt"
func main() {
m := map[int]string{
1: "haha",
2: "哈哈",
}
//使用匿名变量接收key
for _, value := range m {
fmt.Printf("value: %s\n", key, value)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
代码输出:
value: haha
value: 哈哈
2
# switch 语句(分支判断)
在Go语言中, switch 中的每一个 case 都是独立代码块,无需通过 break 语句跳出代码块,以避免执行到下一个 case 代码块。
比如
JAVA和C/C++语言case代码块中的break语句印象深刻。
# 基本格式
switch 表达式 {
case 目标值1:
执行语句
case 目标值2:
执行语句
default:
执行语句
}
2
3
4
5
6
7
8
- 表达式:可以是变量,也可以是一系列计算公式
- 目标值:根表达式比对的值,如果匹配就会执行对应的执行语句
- default:如果前面
case的目标值都不匹配,就会执行defalut里面的执行语句,每一个swtich语句中只能有一个default分支,也可省略不写
例子:
package main
import "fmt"
func main() {
num := 1
switch num {
case 1:
fmt.Println("我是1")
case 2:
fmt.Println("我是2")
default:
fmt.Println("我是default")
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
代码输出:
我是1
# 一分支多值
表达式直接用逗号 , 隔开即可:
package main
import "fmt"
func main() {
num := 1
switch num {
case 1, 2:
fmt.Println("1和2都是我")
default:
fmt.Println("我是default")
}
}
2
3
4
5
6
7
8
9
10
11
12
13
代码输出:
1和2都是我
不需要像JAVA那样需要声明多个case:
//java写法
switch (num) {
case 1:
case 2:
System.out.println("1和2都是我")
default:
System.out.println("我是default")
}
2
3
4
5
6
7
8
# 分支表达式
case 后面除了定义常量以外,还可以像if 语句一样添加表达式,这个时候,switch 后面不再跟判断变量,直接不写即可。
package main
import "fmt"
func main() {
num := 1
switch {
case num > 0 && num < 2:
fmt.Println("大于0小于2")
}
}
2
3
4
5
6
7
8
9
10
11
12
代码输出:
大于0小于2
# fallthrough 关键字 —— 兼容 C 语言的 case 设计
Go 语言中 swtich 语句中的 case 均为独立代码块,执行完成后,不会像 JAVA和C/C++ 语言如果不加break关键字的话会继续执行下一个 case,如果要实现继续执行下一个case的话,可以用 fallthrough 关键字来实现这一功能。
package main
import "fmt"
func main() {
num := 1
switch {
case num > 0:
fmt.Println("大于0")
fallthrough
case num < 2:
fmt.Println("小于2")
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
代码输出:
大于0
小于2
2
# goto 语句(代码跳转)
学
JAVA的可能不知道goto,但在JAVA中goto是一个保留字,只是暂时没有用处,但学过C/C++的就比较熟悉了。
goto 语句通过标签实现代码间的跳转。它通常会被使用在快速跳出循环、避免定义重复代码等。
package main
import "fmt"
func main() {
// 外循环
for i := 0; i < 10; i++ {
fmt.Println(i)
//当i等于5的时候跳转到breakHere标签
if i == 5 {
goto breakHere
}
}
// 定义一个标签
breakHere:
fmt.Println("跳到这里 ...")
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
代码输出:
0
1
2
3
4
5
跳到这里 ...
2
3
4
5
6
7
# break 语句(跳出循环)
break 语句可以结束 for、switch 和 select 代码块。
# 跳出单层循环
当循环到 6 时,通过 break 语句跳出循环:
package main
import "fmt"
func main() {
// 外循环
for i := 0; i < 10; i++ {
fmt.Printf("i: %d\n", i)
// 当 i 等于 6 时,跳转到循环
if i == 6 {
// 跳出循环
break
}
}
fmt.Println("跳出循环 ...")
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
代码输出:
i: 0
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
跳出循环 ...
2
3
4
5
6
7
8
# 跳出代码块 - 退出多层循环
通过 break 语句搭配标签可以跳出代码块,如跳出 for 、switch 和 select 代码块。
package main
import "fmt"
func main() {
//定义一个标签
OuterLoop:
// 外循环
for i := 0; i < 10; i++ {
fmt.Printf("i: %d\n", i)
// 内循环
for j := 0; j < 10; j++ {
fmt.Printf("j: %d\n", j)
if i == 0 && j == 6 {
// 跳出 OuterLoop 代码块
break OuterLoop
}
}
}
fmt.Println("跳出循环 ...")
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
代码输出:
i: 0
j: 0
j: 1
j: 2
j: 3
j: 4
j: 5
j: 6
跳出循环 ...
2
3
4
5
6
7
8
9
# continue 语句(继续下次循环)
continue 语句可以结束当前 for 循环 ,进入下一次 for 循环。
比如循环输出0-9,当i==5的时候跳过输出:
package main
import "fmt"
func main() {
for i := 0; i < 10; i++ {
if i == 5 {
continue
}
fmt.Println(i)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
代码输出:
0
1
2
3
4
6
7
8
9
2
3
4
5
6
7
8
9
另外,我们还可以在 continue 语句后添加标签,表示开始标签处的循环:
package main
import "fmt"
func main() {
//定义一个标签
OuterLoop:
// 外循环
for i := 0; i < 3; i++ {
// 内循环
for j := 0; j < 3; j++ {
// 当 j 等于 1 时,执行 continue 语句跳转到 OuterLoop 标签处,即跳出至外循环,而不是内循环
if j == 1 {
continue OuterLoop
}
fmt.Printf("i: %d, j: %d\n", i, j)
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
代码输出:
i: 0, j: 0
i: 1, j: 0
i: 2, j: 0
2
3