分支循环语句
Go语言的分支循环语句和大多数语言使用起来稍有区别,Go的语法乍一看可能确实比较怪异,但总体思想还是一样的,这篇笔记我们介绍相关的语法。
for 循环
下面代码计算了1-100整数的和。Go语言中,for循环没有括号,而且定义循环变量只能用:=的形式。
package main
import "fmt"
func main() {
var sum = 0
for i := 1; i <= 100; i++ {
sum += i
}
fmt.Println(sum)
}
for range 循环
Go语言中for range用法类似其它语言的for each语法,可以很方便的循环一个数组,不过不要和Python中的range函数弄混淆。
package main
import "fmt"
func main() {
var arr = []string{"tom", "jerry", "lucy"}
for index, name := range arr {
fmt.Println(index, name)
}
}
for语句中声明了两个变量,它们名字是自己任意取的,第一个表示对应元素的数组索引,索引从0开始,第二个是数组元素值。如果只需要索引,第二个变量可以省略。如果不需要索引,可用一个下划线_代替原本的变量。
for _, name := range arr { ... }
“while” 循环
Go语言没有while关键字,而是使用for实现相同的写法。下面例子代码用这种写法实现求1-100整数的和。
package main
import "fmt"
func main() {
var sum = 0
var i = 1
for i <= 100 {
sum += i
i++
}
fmt.Println(sum)
}
如果我们要写一个无限循环,不加任何条件即可。
for {
// ... 循环逻辑
}
if 判断
if写法也是没有括号的,语法和大多数语言相同。
package main
import "fmt"
func main() {
var i = 1
var j = 2
if i < j {
fmt.Println(j)
} else {
fmt.Println(i)
}
}
在if条件内部可以加一条语句,用于对判断条件进行一些处理,非常方便。
if sum := i + j; a < sum { ... }
这个写法在错误处理时很常用,也推荐这样写,下面是一个例子。
if err := conn.Close(); err != nil {
// ... 错误处理逻辑
}
switch 判断
Go语言中的switch终于不用写break了。
package main
import "fmt"
func main() {
var current = 2
switch current {
case 1:
fmt.Println("Good morning!")
case 2:
fmt.Println("Good afternoon!")
case 3:
fmt.Println("Good night!")
default:
fmt.Println("Unrecognized time")
}
}
Go语言还支持另一种switch,这种需要在case后面直接写明判断条件。
package main
import "fmt"
func main() {
var current = 7
switch {
case current <= 7:
fmt.Println("Good morning!")
case current <= 17:
fmt.Println("Good afternoon!")
case current <= 23:
fmt.Println("Good night!")
default:
fmt.Println("Unrecognized time")
}
}
defer语句
Go语言支持一个比较特别的defer语句,它用于注册延迟调用代码,defer后面的函数调用不会立即执行,而是被推迟到其所在函数返回之前才执行,如果一个函数中有多个defer语句,它们会按照后进先出(LIFO)的顺序执行,简单记忆就是后注册的defer先执行。
package main
import "fmt"
func test() {
defer fmt.Println("func test defer1")
defer fmt.Println("func test defer2")
fmt.Println("func test return")
}
func main() {
test()
fmt.Println("func main return")
}
执行结果:
func test return
func test defer2
func test defer1
func main return
有时defer逻辑可能比较复杂,包含不止一行代码,此时我们可以使用defer调用函数或是编写一个自执行函数,下面是一个例子。
defer func(conn net.Conn) {
if err := conn.Close(); err != nil {
fmt.Println(err)
return
}
}(conn)
defer常用于资源清理(关闭文件、释放锁)、记录日志等逻辑,它能保证无论函数从哪个分支返回,包括发生panic时,清理逻辑都会被执行。