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)
}
}
注意: 这里的
i
、v
是切片元素的位置索引和值。可以通过赋值给
_
来忽略序号和值。【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)
}
}
注意: 这里的
i
、v
是 map
的 一组键值对的键和值。Go同样也可以使用
continue
和 break
对循环进行控制,例如: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)
的近似值:文章图片
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
输出结果:
文章图片
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的最后一个分支。
switch
的 case
条件可以是多个值,例如: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.")
}
}
小技巧: 使用
switch
对 interface{}
进行断言,例如: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")
}
输出结果:
文章图片
defer 栈
延迟的函数调用被压入一个栈中。当函数返回时, 会按照后进先出的顺序调用被延迟的函数调用。
package mainimport "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
推荐阅读
- Go|Docker后端部署详解(Go+Nginx)
- GO|GO,GO,GO!
- Go成长之路|go中判断空字符串、nil和len(t)的用法
- go编译tools
- go grpc安装与使用
- goroutine 调度原理
- Go|Go进阶之路——复杂类型
- Go进阶之路——变量