概述 控制语句很好理解,即循环、条件等控制代码执行流程的语句,这些语句在Go中的形式与其他语言的差别也很小
循环语句 Go只有for循环一种循环语句
一个基本的for语句由三部分组成,每部分用分号隔开
初始化:在第一次迭代前执行
条件表达式: 在每次迭代前进行判断,一旦布尔值为false,循环就会终止
后置语句:在每次迭代的结尾执行
初始化语句通常为一个短变量声明,该声明仅在for语句的作用域中可见
示例1:for.go
1 2 3 4 5 6 7 8 9 10 11 package mainimport "fmt" func main () { sum := 0 for i := 0 ; i < 10 ; i++ { sum += i } fmt.Println(sum) }
与其他语言像C、Java等语言不同的是,Go的for语句后面三个部分外没有(),但{}是必需的
示例1编译运行后可以看到程序输出结果
for循环的三个部分中初始化语句和后置语句是可选项,例如
1 2 3 4 5 6 sum := 1 for ; sum < 1000 ; { sum += sum }
编译运行后输出结果1024,可以看出每次循环都执行sum += sum直到sum的值大于等于1000
在这种情况下把语句中的分号去掉,很容易看出来这就是其他语言中的while循环
1 2 3 4 5 sum := 1 for sum < 1000 { sum += sum }
至此我们已经省略了for循环三部分中的两部分,如果将剩下的一个部分————条件表达式也省略,这是这个循环就成了无限循环
条件语句 条件语句包括if、switch等对条件进行判断的语句
if语句 与for类似,if语句无需()而{}是必须的,基本形式的的if语句只有一个部分————条件表达式
示例2:if.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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语句允许在条件表达式前执行一个简单的语句,该语句声明的变量作用域仅在if之内
示例3:if-with-a-short-statement.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 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语句,if语句中的声明在else语句中同样可以使用
对示例3中pow函数稍作修改
1 2 3 4 5 6 7 8 9 10 11 12 13 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) } return lim }
编译运行
注意
实际在main的fmt.Println调用之前对pow函数调用就已经执行完成并返回各自的结果
一个小小的练习 练习1:用牛顿法实现平方根函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package mainimport ( "fmt" ) func Sqrt (x float64 ) float64 { z := float64 (1 ) for i:=0 ; i < 10 ; i++ { z -= (z*z - x) / (2 *z) fmt.Println(i,": " ,z,"\n" ) } return z } func main () { fmt.Println(Sqrt(2 )) }
编译运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 0 : 1.5 1 : 1.4166666666666667 2 : 1.4142156862745099 3 : 1.4142135623746899 4 : 1.4142135623730951 5 : 1.414213562373095 6 : 1.4142135623730951 7 : 1.414213562373095 8 : 1.4142135623730951 9 : 1.414213562373095 1.414213562373095
换一种实现方法,当z的值停止改变时退出循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package mainimport ( "fmt" ) func Sqrt (x float64 ) float64 { z := float64 (1 ) i := 0.0 for j := 0 ; j >= 0 ; j++ { if i != z { i = z z -= (z*z - x) / (2 *z) } else { return z } fmt.Println(j,":" ,z,"\n" ) } return z } func main () { fmt.Println(Sqrt(2 )) }
什么是牛顿法:
z² − x 是 z² 到它所要到达的值(即 x)的距离, 除以的 2z 为 z² 的导数,我们通过 z² 的变化速度来改变 z 的调整量。 这种通用方法叫做牛顿法。 它对很多函数,特别是平方根而言非常有效。
switch语句 switch是编写一连串if-else语句的简便写法,它运行第一个值等于条件表达式的case语句,语法结构如下:
1 2 3 4 5 6 7 8 switch var { case val1 : ... case val2 : ... default : ... }
其中var可以是任何类型,val1和val2则是同类型的任意值。
case语句从上到下顺序执行,直到匹配成功。默认情况下Go不会运行之后所有的case语句,即自带break语句。如果需要执行后面的case语句,则需要以fallthrough语句结束。
示例4:switch.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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 : fmt.Printf("%s.\n" , os) } }
编译运行
switch语句允许没有条件表达式,其等价于switch true,这种形式在面对一长串的if-then-else情况下可以写出更清晰的代码
defer语句 defer语句的功能是延迟执行,defer语句会将函数推迟到外层函数返回后再执行,推迟调用的函数其参数会立即求值,但是直到外层函数返回前该函数都不会被调用。
示例5:defer.go
1 2 3 4 5 6 7 8 9 package mainimport "fmt" func main () { defer fmt.Println("world" ) fmt.Println("hello" ) }
编译运行
多个defer语句的调用遵循后进先出,即推迟执行的函数会被压入一个栈中
示例6:defer-more.go
1 2 3 4 5 6 7 8 9 10 11 12 13 package mainimport "fmt" func main () { fmt.Println("counting" ) for i := 0 ;i < 10 ; i++ { defer fmt.Println(i) } fmt.Println("done" ) }
编译运行
1 2 3 4 5 6 7 8 9 10 11 12 counting done 9 8 7 6 5 4 3 2 1 0