通用技术 Go--Go 基础之流程控制语句

stack · 2017年06月01日 · 最后由 bauul 回复于 2017年06月01日 · 1787 次阅读

For

Go 只有一种循环结构,那就是 for 循环。

一般形式

虽然只有一种循环,但为了满足不同的需求,也提供了许多形式,一般形式如下:

  1. initialization 部分:在循环开始之前进行;一般是变量的初始化;
  2. condition 部分:每次循环之前都要执行;一般是布尔表达式,判断为真则循环,判断为假则结束循环;
  3. post 部分:在每次循环迭代结束之后都要执行;一般是对 condition 部分的变量进行修改;

condition 部分在下一次循环之前再次进行判断,如此往复,形成循环。

示例:for.go

package main

import "fmt"

func main() {
    sum := 0
    for i := 0; i < 10; i++ {
        sum += i
    }
    fmt.Println(sum)
}

注意点:

  1. for 循环的大括号不可省略,且左括号必须和 for 循环在一行上。

如果 for 循环部分写成:

for i := 0; i < 10; i++ 
{
    sum += i
}

​ 执行会报错:

# command-line-arguments
.\for.go:7: syntax error: missing { after for clause
  1. for 循环 initialization 部分的变量仅可用于 for 循环部分,在 for 循环体之外不可使用。

fmt.Println(sum)下添加语句fmt.Println(i)执行会报错:

# command-line-arguments
.\for.go:11: undefined: i

省略形式

  • initialization 部分和 post 部分可省略;

示例:

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 部分可省略

如果省略 condition 部分,循环将永久执行(即 死循环)。

示例:forever.go

package main

func main() {
  for {
  }
}

If

If

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))
}

带短句的 If

和 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 中声明的变量在 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 的形式,是不是似曾相似?

在 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 语句(和其机制)我还是第一次碰到。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 语句中的变量的值早已确定,但函数的调用是延迟的。

Stacking defers

延迟的栈调用被压入到一个栈中。当函数返回时,它的延迟调用按照后进先出的顺序被执行。

示例: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 来实现。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 1 条回复 时间 点赞

有种回到 qbasic 的感觉

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册