学习 A Tour of Go (中文参考 Go 之旅中文 ) 整理的笔记。介绍流程控制语句 for
, if
, else
, switch
和 defer
的基本概念和使用。
1. for
$GOPATH/src/go_note/gotour/flowcontrol/for.go
源码如下:
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 31 32 |
/** * go 语言for 循环 */ package main import ( "fmt" ) func main() { sum := 0 for i := 0; i < 10; i ++ { sum += i } fmt.Println("sum:", sum) // sum: 45 // 初始化语句和后置语句是可选的 sum = 1 for ; sum < 1000; { sum += sum } fmt.Println("sum:", sum) // sum: 1024 // 去掉分号 `;`, `for` 是 Go 中的 `while` sum = 1 for sum < 1000 { sum += sum } fmt.Println("sum:", sum) // sum: 1024 } |
Go 只有一种循环结构:for
循环。基本的 for 循环由三部分组成,用分号隔开:
- 初始化语句:在第一次迭代前执行
- 条件表达式:在每次迭代前求值
- 后置语句:在每次迭代的结尾执行
初始化语句通常为一句短变量声明,该变量声明仅在 for
语句的作用域中可见。Go 的 for
语句后面没有小括号,大括号 { }
则是必须的。
1.1 for 是 Go 中的 while
初始化语句和后置语句是可选的,此时你可以去掉分号 ;
, for
是 Go 中的 while
1 2 3 4 5 6 7 |
// 掉分号 `;`, `for` 是 Go 中的 `while` sum := 1 for sum < 1000 { sum += sum } fmt.Println("sum: ", sum) |
1.2 无限循环
如果省略循环条件,该循环就不会结束,循环成为一个无线循环。
1 2 3 4 5 |
func main() { for { } } |
2. if else
$GOPATH/src/go_note/gotour/flowcontrol/if/if.go
源码如下:
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 31 32 33 34 35 36 37 38 39 |
/** * go if 控制语句 */ package main import ( "fmt" "math" ) func sqrt(x float64) string { // 表达式外无需小括号 if x < 0 { return sqrt(-x) + "i" } return fmt.Sprint(math.Sqrt(x)) } func pow(x, n, lim float64) float64 { // 条件表达式前可以执行一个简单的语句 if v := math.Pow(x, n); v < lim { return v } else { // 表达式前执行简单的语句,语句声明的变量作用域仅在 if 和对应的 else 块中使用 fmt.Printf("%g >= %g\n", v, lim) } return lim } func main() { fmt.Println(sqrt(2), sqrt(-4)) fmt.Println( pow(3, 2, 10), pow(3, 3, 20), ) } |
Go 的 if
语句与 for
循环类似,表达式外无需小括号 ( )
,而大括号 { }
则是必须的。
2.1 if 的简短语句
同 for
一样, if
语句可以在条件表达式前执行一个简单的语句,该语句声明的变量作用域仅在 if
和对应的 else
块中使用。
1 2 3 4 5 6 7 8 9 10 11 |
func pow(x, n, lim float64) float64 { // 条件表达式前可以执行一个简单的语句 if v := math.Pow(x, n); v < lim { return v } else { // 表达式前执行简单的语句,语句声明的变量作用域仅在 if 和对应的 else 块中使用 fmt.Printf("%g >= %g\n", v, lim) } return lim } |
3. switch
$GOPATH/src/go_note/gotour/flowcontrol/switch/switch.go
源码如下:
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 31 32 33 34 35 36 37 |
/** * go switch 控制语句 */ package main import ( "fmt" "time" ) func main() { switch i := 1; i { case 0: fmt.Println(0) case 1: fmt.Println(1) fallthrough // 除非以 fallthrough 语句结束,否则分支会自动终止 default: fmt.Println(2) } // 以上代码段输出 // 1 // 2 // 没有条件的 switch t := time.Now() switch { case t.Hour() < 12: fmt.Println("早上好!") case t.Hour() < 17: fmt.Println("下午好!") default: fmt.Println("晚上好!") } } |
Go 语言switch
除非以 fallthrough
语句结束,否则分支会自动终止。switch
的 case
语句从上到下顺次执行,直到匹配成功时停止。
没有条件的 switch
同 switch true
一样,这种形式能将一长串 if-then-else
写得更加清晰。
4. defer
$GOPATH/src/go_note/gotour/flowcontrol/defer/defer.go
源码如下:
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 31 32 33 34 35 |
/** * go defer 控制语句 */ package main import "fmt" func print() { defer fmt.Println("world") fmt.Println("hello") } func main() { print() fmt.Println("counting") for i := 0; i < 10; i++ { defer fmt.Println(i) } fmt.Println("done") // counting // done // 9 // 8 // 7 // 6 // 5 // 4 // 3 // 2 // 1 // 0 } |
defer 语句会将函数推迟到外层函数返回之后执行。推迟调用的函数其参数会立即求值,但直到外层函数返回前该函数都不会被调用。推迟的函数调用会被压入一个栈中。 当外层函数返回时,被推迟的函数会按照后进先出的顺序调用。
参考
有疑问加站长微信联系(非本文作者)