Go 只有一种循环结构,那就是 for 循环。
虽然只有一种循环,但为了满足不同的需求,也提供了许多形式,一般形式如下:
condition 部分在下一次循环之前再次进行判断,如此往复,形成循环。
示例:for.go
package main
import "fmt"
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
}
注意点:
如果 for 循环部分写成:
for i := 0; i < 10; i++
{
sum += i
}
执行会报错:
# command-line-arguments
.\for.go:7: syntax error: missing { after for clause
在fmt.Println(sum)
下添加语句fmt.Println(i)
执行会报错:
# command-line-arguments
.\for.go:11: undefined: i
示例:
package main
import "fmt"
func main() {
sum := 1
for ; sum < 1000; {
sum += sum
}
fmt.Println(sum)
}
以上代码中的 for 循环部分,在LiteIDE
中执行时会自动变为:
for sum < 1000 {
sum += sum
}
initialization 部分和 post 部分可以省略,分号也可以省略,这也是 for 的另一种形式
。
如果省略 condition 部分,循环将永久执行(即 死循环
)。
示例:forever.go
package main
func main() {
for {
}
}
Go 的 if 语句和它的 for 循环语句很相似:
表达式不需要圆括号;但大括号却是必需的,且左大括号不能单独在一行。
示例:if.go
package main
import (
"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))
}
和 for 语句类似,if 语句可以在条件判断之前执行一个简短的语句。
这个短语句中的变量仅可以在 if 结束之前使用,即作用域是 if 语句中。
示例:if-with-a-short-statement.go
package main
import (
"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, 2, 20),
pow(3, 2, 8),
)
}
如果在return lim
语句的上面添加语句fmt.Println(v)
,执行报错:
# command-line-arguments
.\if-with-a-short-statement.go:12: undefined: v
在 if - else 语句中,在 if 中声明的变量在 else 代码块中依然可以使用。
示例:if-and-else.go
package main
import (
"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)
}
return lim
}
func main() {
fmt.Println(
pow(3, 2, 10),
pow(3, 2, 20),
pow(3, 2, 7),
)
}
看看 switch 的形式,是不是似曾相似?
在 switch 语句中使用的表达式必须具有整数或布尔表达式,或者是一个具有单个转换函数为整数或布尔值的类类型。如果未传递表达式,则默认值为true
。
在 switch 语句中可以有任意数量的 case 语句。 每个 case 后面都跟要比较的值和冒号。
case 的常量表达式必须是与 switch 语句的变量是相同的数据类型,并且它必须是常量或文字。
当被 switch 打开的变量等于一个 case 中的值,那么将执行 case 之后的语句。在 case 语句中不需要 break 语句。
switch 语句可有一个可选的 default,它必须出现在 switch 语句的末尾。 default 可用于在没有任何 case 为真时执行任务。default 之后也不需要 break 语句。
switch 语句能够简化if-else
语句,尤其是当if-else
比较复杂时。
示例:switch.go
package main
import (
"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)
}
}
switch 的 case 判断顺序是自上而下的,当某一个 case 匹配成功时停止。
defer 语句(和其机制)我还是第一次碰到。defer 这个单词是延迟的意思,相必是 Go 语言为了某种特定需求而提供的一种机制,隐约觉得它必有大用途
。
defer 语句延迟函数的执行,直到周围的函数已返回。
示例:defer.go
package main
import "fmt"
func main() {
v := 2
defer fmt.Println("v is:", v)
v = v + 1
fmt.Println("v now is:", v)
defer fmt.Println("v is:", v)
v = v + 1
fmt.Println("v now is:", v)
}
输出:
v now is: 3
v now is: 4
v is: 3
v is: 2
从上面例子中还能看出,defer 语句中的变量的值早已确定,但函数的调用是延迟的。
延迟的栈调用被压入到一个栈中。当函数返回时,它的延迟调用按照后进先出
的顺序被执行。
示例:defer-multi.go
package main
import "fmt"
func main() {
fmt.Println("counting")
for i := 0; i < 10; i++ {
//defer fmt.Println(i)
fmt.Println(i)
}
fmt.Println("done")
}
结果:
counting
0
1
2
3
4
5
6
7
8
9
done
如果将fmt.Println(i)
修改为defer fmt.Println(i)
:
counting
done
9
8
7
6
5
4
3
2
1
0
流程控制语句的主要内容就这么多,有了这些基础,你可以读读其它 Go 教材的有关部分做个补充,或者找些其它编程语言的流程控制语句的练习题,用 Go 来实现。