Go 只有一种循环结构——`for` 循环。
基本的 for
循环除了没有了 `( )` 之外(甚至强制不能使用它们),看起来跟 C 或者 Java 中的一样,而 `{ }` 是必须的。
package main
import "fmt"
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
}
跟 C 或者 Java 中一样,也可以让前置、后置语句为空。
package main
import "fmt"
func main() {
sum := 1
for ; sum < 1000; {
sum += sum
}
fmt.Println(sum)
}
这种方式可以取代C和Java中的while循环方式。
也可以使用 for..range
对数组、切片、map、 字符串等进行循环操作,例如:
package main
import "fmt"
func main() {
numbers := []int{1, 2, 3}
for i, v := range numbers {
fmt.Printf("numbers[%d] is %d\n", i, v)
}
}
注意: 这里的 i
、v
是切片元素的位置索引和值。
可以通过赋值给 _
来忽略序号和值。
如果只需要索引值,去掉“, v”的部分即可。
package main
import "fmt"
func main() {
cityCodes := map[string]int{
"北京": 1,
"上海": 2,
}
for i, v := range cityCodes {
fmt.Printf("%s is %d\n", i, v)
}
}
注意: 这里的 i
、v
是 map
的 一组键值对的键和值。
Go同样也可以使用 continue
和 break
对循环进行控制,例如:
package main
import "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 main
func main() {
for {
}
}
if
语句除了没有了 `( )` 之外(甚至强制不能使用它们),看起来跟 C 或者 Java 中的一样,而 `{ }` 是必须的。
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))
}
还可以使用 if
..else if
..else
来实现多分支的条件判断:
package main
import "fmt"
func main() {
age := 13
if 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 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, 3, 20),
)
}
在 if
的便捷语句定义的变量同样可以在任何对应的 else
块中使用。
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)
}
// 这里开始就不能使用 v 了
return lim
}
练习例子:
用牛顿法实现开方函数。
牛顿法是通过选择一个初始点 z 然后重复这一过程求 Sqrt(x)
的近似值:
package main
import (
"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
输出结果:
如果我们的条件分支太多,可以考虑使用 switch
替换 if
, 例如:
package main
import "fmt"
func main() {
age := 10
switch 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 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)
}
}
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的最后一个分支。
switch
的 case
条件可以是多个值,例如:
package main
import "fmt"
func main() {
age := 7
switch 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 true` 一样。
这一构造使得可以用更清晰的形式来编写长的 if-then-else 链。
package main
import (
"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.")
}
}
小技巧: 使用 switch
对 interface{}
进行断言,例如:
package main
import "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 语句会延迟函数的执行直到上层函数返回。
延迟调用的参数会立刻生成,但是在上层函数返回前函数都不会被调用。
package main
import "fmt"
func main() {
defer fmt.Println("world")
fmt.Println("hello")
}
输出结果:
延迟的函数调用被压入一个栈中。当函数返回时, 会按照后进先出的顺序调用被延迟的函数调用。
package main
import "fmt"
func main() {
fmt.Println("counting")
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
fmt.Println("done")
}
输出结果:
更多了解https://blog.golang.org/defer-panic-and-recover