Go漫游笔记-04-流程控制

条件语句

if-else

结构上 Java 的 if-else 语句类似,但是,也有一些明显的区别:

  • 条件表达式可以省略 ()

    1
    2
    3
    4
    5
    if a > 0 {
    // some code
    } else {
    // some code
    }
  • 支持初始化语句,位于条件语句之前,使用 ; 分隔!

    1
    2
    3
    if b := 0; a > 0 {
    a = b
    }
  • 语句体必须{} 包裹起来,并且 { 必须与 ifelse 位于同一行。

    1
    2
    3
    4
    if a > 0   // syntax error: missing { after if clause
    {
    // some code
    }
  • 由于 1.1 以下的版本无法解析出 else 中的返回值,因此,使用低版本开发的时候需要注意以下代码,会编译失败:

    1
    2
    3
    4
    5
    6
    7
    func isEven(integer int32) bool {
    if integer%2 == 0 {
    return true
    } else {
    return false // 1.1 以后没问题
    }
    }

另外,目前 Go 语言还不支持三元操作符: x > y ? true : false ,有点遗憾。

switch

Go 的 switch 也很有特点:

  • case 可以同时匹配多个选项,可以省略 break,因为会默认自动终止执行分支。只有显式声明 fallthrough 的时候,才会继续执行下一个分支。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    a := []int{1, 2, 3, 4}
    i := 2
    switch i {
    case a[0]:
    fmt.Println("1") // 默认自动终止
    case 2:
    fmt.Println("2")
    fallthrough // 会继续执行下一个分支
    case 3, 4: // 可以同时匹配多个选项
    fmt.Println("3 or 4")
    default:
    fmt.Println("unknown")
    }
  • switch 后面的表达式甚至不是必需的,这样一来,就可以当 if-else if-…-else 来用了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    v := 10
    switch {
    case v > 0:
    fmt.Printf("%d > 0\n", v)
    case v < 0:
    fmt.Printf("%d < 0\n", v)
    default:
    fmt.Printf("%d = 0\n", v)
    }

循环语句

Go 的循环语句只支持 for 语句,没有 whiledo-while

for

结构上 Java 的 if-else 语句类似,但是,也有一些明显的区别:

  • 普通写法:

    1
    2
    3
    for i, n := 0, 5; i < n; i++ {
    fmt.Println(i)
    }

    有一点需要注意的:如果需要使用多个控制变量,不能通过 , 分隔,而是要使用多重赋值。

    1
    2
    3
    4
    5
    6
    7
    for i, j, n := 0, 1, 5; i < n; i++, j++ { // 编译失败
    fmt.Printf("%d,%d\n", i, j)
    }

    for i, j, n := 0, 1, 5; i < n; i, j = i+1, j+1 { // OK
    fmt.Printf("%d,%d\n", i, j)
    }
  • while 写法:

    1
    2
    3
    4
    5
    i, n := 0, 5
    for i < n {
    fmt.Println(i)
    i++
    }
  • 无限循环:

    1
    2
    3
    for {
    // some code
    }

range

在 Go 中,如果想遍历一个数组,除了使用上面 for 语句的用法以外,还可以使用 range 关键字来实现。

1
2
3
4
a := [3]int32{1, 2, 3}
for index, value := range a {
fmt.Println(index, value)
}

range 的概念,有点类似于 Java 中的迭代器 Iterator ,它除了支持数组的遍历,还支持: stringslicemap

使用 range 时,有一点是需要注意的,就是它会复制被遍历的对象。
通过下面的例子就不难理解了:

1
2
3
4
5
6
7
a := [3]int32{1, 2, 3}
for index, value := range a {
a[index] = value + 1 // 直接修改数组元素
fmt.Println(index, value) // 上面的操作对 value 并没有影响,因为 value 是复制品
value++ // 同样的, value 的修改对于原数组而言也是无效的
}
fmt.Println(a) // [2 3 4] 数组的修改操作是有效的

中断语句

goto

Go 支持在函数内使用 goto 实现跳转,用法和其它语言类似。

1
2
3
4
5
6
7
8
9
i := 0
for {
i++
if i > 3 {
goto EXIT
}
}
EXIT:
fmt.Println(i) // 4

continue/break

continuebreak 一般用于循环语句,用法和其它语言也是类似的。
continue 会将控制转移到当前循环的起点。
break 则是彻底跳出当前的循环。

1
2
3
4
5
6
7
8
9
10
11
for i = 0; i < 3; i++ {
if i == 1 {
continue // 转移到当前循环的起点
}
for j := 0; j < 3; j++ {
if j == 1 {
break // 跳出当前的循环
}
fmt.Println(i, j)
}
}

需要注意的是:
continue 只能用于 for 语句。
break 则可以用于 forswitch 以及 select (后面再提)。