Go进阶之路——流程控制语句

for Go 只有一种循环结构——`for` 循环。
基本的 for 循环除了没有了 `( )` 之外(甚至强制不能使用它们),看起来跟 C 或者 Java 中的一样,而 `{ }` 是必须的。

package mainimport "fmt"func main() { sum := 0 for i := 0; i < 10; i++ { sum += i } fmt.Println(sum) }

跟 C 或者 Java 中一样,也可以让前置、后置语句为空。
package mainimport "fmt"func main() { sum := 1 for ; sum < 1000; { sum += sum } fmt.Println(sum) }

这种方式可以取代C和Java中的while循环方式。
也可以使用 for..range 对数组、切片、map、 字符串等进行循环操作,例如:
package mainimport "fmt"func main() { numbers := []int{1, 2, 3}for i, v := range numbers { fmt.Printf("numbers[%d] is %d\n", i, v) } }

注意: 这里的 iv 是切片元素的位置索引和值。
可以通过赋值给 _ 来忽略序号和值。
【Go进阶之路——流程控制语句】如果只需要索引值,去掉“, v”的部分即可。
package mainimport "fmt"func main() { cityCodes := map[string]int{ "北京": 1, "上海": 2, }for i, v := range cityCodes { fmt.Printf("%s is %d\n", i, v) } }

注意: 这里的 ivmap 的 一组键值对的键和值。
Go同样也可以使用 continuebreak 对循环进行控制,例如:
package mainimport "fmt"func main() { numbers := []int{1, 2, 3, 4, 5}for i, v := range numbers { if v == 4 { break }if v%2 == 0 { continue }fmt.Printf("numbers[%d] is %d\n", i, v) } }

死循环
如果省略了循环条件,循环就不会结束,因此可以用更简洁地形式表达死循环。
package mainfunc main() { for { } }

if if 语句除了没有了 `( )` 之外(甚至强制不能使用它们),看起来跟 C 或者 Java 中的一样,而 `{ }` 是必须的。
package mainimport ( "fmt" "math" )func sqrt(x float64) string { if x < 0 { return sqrt(-x) + "i" } return fmt.Sprint(math.Sqrt(x)) }func main() { fmt.Println(sqrt(2), sqrt(-4)) }

还可以使用 if..else if..else 来实现多分支的条件判断:
package mainimport "fmt"func main() { age := 13if age > 6 && age <= 12 { fmt.Println("It's primary school") } else if age > 12 && age <= 15 { fmt.Println("It's middle school") } else { fmt.Println("It's high school") } }

for 一样,`if` 语句可以在条件之前执行一个简单的语句(if 的便捷语句)。
由这个语句定义的变量的作用域仅在 if 范围之内。
package mainimport ( "fmt" "math" )func pow(x, n, lim float64) float64 { if v := math.Pow(x, n); v < lim { return v } return lim }func main() { fmt.Println( pow(3, 2, 10), pow(3, 3, 20), ) }

if 的便捷语句定义的变量同样可以在任何对应的 else 块中使用。
package mainimport ( "fmt" "math" )func pow(x, n, lim float64) float64 { if v := math.Pow(x, n); v < lim { return v } else { fmt.Printf("%g >= %g\n", v, lim) } // 这里开始就不能使用 v 了 return lim }

练习例子:
用牛顿法实现开方函数。
牛顿法是通过选择一个初始点 z 然后重复这一过程求 Sqrt(x) 的近似值:

Go进阶之路——流程控制语句
文章图片

package mainimport ( "fmt" "math" )func Sqrt(x float64) float64 { z := float64(1) for { temp := z - (z*z-x)/(2*z) if temp==z || (temp>z && temp-z<0.00000001) || (temp

输出结果:
Go进阶之路——流程控制语句
文章图片

switch 如果我们的条件分支太多,可以考虑使用 switch 替换 if, 例如:
package mainimport "fmt"func main() { age := 10switch age { case 5: fmt.Println("The age is 5") case 7: fmt.Println("The age is 7") case 10: fmt.Println("The age is 10") default: fmt.Println("The age is unkown") } }

同if,switch后也可以添加一个简单的语句
package mainimport ( "fmt" "runtime" )func main() { fmt.Print("Go runs on ") switch os := runtime.GOOS; os { case "darwin": fmt.Println("OS X.") case "linux": fmt.Println("Linux.") default: // freebsd, openbsd, // plan9, windows... fmt.Printf("%s.", os) } }

ps:GOOS是可执行程序的目标操作系统(将要在该操作系统的机器上执行):darwin、freebsd、linux等。
注意:在 Go 中 switch 只要匹配中了就会中止剩余的匹配项,直接跳出整个switch,这和 Java 很大不一样,java需要使用 break 来主动跳出。
但是可以使用 fallthrough 强制执行后面的case代码。
switch { case false: fmt.Println("The integer was <= 4") fallthrough case true: fmt.Println("The integer was <= 5") fallthrough case false: fmt.Println("The integer was <= 6") fallthrough case true: fmt.Println("The integer was <= 7") fallthrough case false: fmt.Println("The integer was <= 8") default: fmt.Println("default case") }

但也要注意,fallthrough 不能用在switch的最后一个分支。
switchcase 条件可以是多个值,例如:
package mainimport "fmt"func main() { age := 7switch age { case 7, 8, 9, 10, 11, 12: fmt.Println("It's primary school") case 13, 14, 15: fmt.Println("It's middle school") case 16, 17, 18: fmt.Println("It's high school") default: fmt.Println("The age is unkown") } }

注意: 同一个 case 中的多值不能重复。
没有条件的 switch
没有条件的 switch 同 `switch true` 一样。
这一构造使得可以用更清晰的形式来编写长的 if-then-else 链。
package mainimport ( "fmt" "time" )func main() { t := time.Now() switch { case t.Hour() < 12: fmt.Println("Good morning!") case t.Hour() < 17: fmt.Println("Good afternoon.") default: fmt.Println("Good evening.") } }

小技巧: 使用 switchinterface{} 进行断言,例如:
package mainimport "fmt"func checkType(i interface{}) { switch v := i.(type) { case int: fmt.Printf("%v is an in\n", v) case string: fmt.Printf("%v is a string\n", v) default: fmt.Printf("%v's type is unkown\n", v) } }func main() { checkType(8) checkType("hello, world") }

defer defer 语句会延迟函数的执行直到上层函数返回。
延迟调用的参数会立刻生成,但是在上层函数返回前函数都不会被调用。
package mainimport "fmt"func main() { defer fmt.Println("world") fmt.Println("hello") }

输出结果:
Go进阶之路——流程控制语句
文章图片

defer 栈
延迟的函数调用被压入一个栈中。当函数返回时, 会按照后进先出的顺序调用被延迟的函数调用。
package mainimport "fmt"func main() { fmt.Println("counting") for i := 0; i < 10; i++ { defer fmt.Println(i) } fmt.Println("done") }

输出结果:
Go进阶之路——流程控制语句
文章图片

更多了解https://blog.golang.org/defer-panic-and-recover

    推荐阅读