分支循环语句

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语句对应的执行流程地址入栈,如果defer语句有多个,它们会按照出栈顺序执行。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)
作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap