Golang学习-CH4 Go语言流程控制


目录
  • 4.1 Go语言if-else分支结构
  • 4.2 Go语言for循环结构
  • 4.3 Go语言for range(键值循环)
  • 4.4 Go语言switch case语句
    • 基本写法
    • 一分支多值
    • 分支表达式
    • 跨越 case 的 fallthrough
  • 4.5 Go语言goto语句——跳转到指定的标签
  • 4.6 Go语言break(跳出循环)
  • 4.7 Go语言continue(继续下一次循环)

4.1 Go语言if-else分支结构

if condition1 {
    // do something
} else if condition2 {
    // do something else
}else {
    // catch-all or default
}

关键字 if 和 else 之后的左大括号{必须和关键字在同一行,如果你使用了 else if 结构,则前段代码块的右大括号}必须和 else if 关键字在同一行,这两条规则都是被编译器强制规定的。

特殊写法:可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断

if err := Connect(); err != nil {
    fmt.Println(err)
    return
}

这种写法可以将返回值与判断放在一行进行处理,而且返回值的作用范围被限制在 if、else 语句组合中。

在编程中,变量的作用范围越小,所造成的问题可能性越小。

4.2 Go语言for循环结构

Go语言中的循环语句只支持 for 关键字,而不支持 while 和 do-while 结构

sum := 0
for i := 0; i < 10; i++ {
    sum += i
}
  • 左花括号{必须与 for 处于同一行。

  • Go语言中的 for 循环与C语言一样,都允许在循环条件中定义和初始化变量,唯一的区别是,Go语言不支持以逗号为间隔的多个赋值语句,必须使用平行赋值的方式来初始化多个变量

  • Go语言的 for 循环同样支持 continue 和 break 来控制循环,但是它提供了一个更高级的 break,可以选择中断哪一个循环。

    JLoop:
    //解决了C++中break跳两层循环时需要标识变量的问题
    for j := 0; j < 5; j++ {
        for i := 0; i < 10; i++ {
            if i > 5 {
                break JLoop
            }
            fmt.Println(i)
        }
    }
    
  • Go语言无限死循环

    var i int
    //C 风格
    for ; ; i++ {
        if i > 10 {
            break
        }
    }
    //go为了解决上述C风格
    for {
        if i > 10 {
            break
        }
        i++
    }
    
  • 只有一个循环条件的循环

    //类似while
    var i int
    for i <= 10 {
        i++
    }
    

4.3 Go语言for range(键值循环)

for range 结构是Go语言特有的一种的迭代结构,在许多情况下都非常有用,for range 可以遍历数组、切片、字符串、map 及通道(channel),for range 语法上类似于其它语言中的 foreach 语句

for key, val := range coll {
    ...
}
//迭代遍历字符串:能够自动根据 UTF-8 规则识别 Unicode 编码的字符。
for pos, char := range str {
    ...
}

需要注意:val 始终为集合中对应索引的值拷贝,因此它一般只具有只读性质,对它所做的任何修改都不会影响到集合中原有的值。

遍历通道:

for range 可以遍历通道(channel),但是通道在遍历时,只输出一个值,即管道内的类型对应的数据。

c := make(chan int)
go func() {
    c <- 1
    c <- 2
    c <- 3
    close(c)
}()
for v := range c {
    fmt.Println(v)	//不断地从通道中取数据,直到通道被关闭。
}

4.4 Go语言switch case语句

Go语言的 switch 要比C语言的更加通用,表达式不需要为常量,甚至不需要为整数,case 按照从上到下的顺序进行求值,直到找到匹配的项,如果 switch 没有表达式,则对 true 进行匹配,因此,可以将 if else-if else 改写成一个 switch。

Go语言改进了 switch 的语法设计,case 与 case 之间是独立的代码块,不需要通过 break 语句跳出当前 case 代码块以避免执行到下一行

解决了C++中常要写break的痛点

基本写法

var a = "hello"
switch a {
case "hello":
    fmt.Println(1)
case "world":
    fmt.Println(2)
default:
    fmt.Println(0)
}

Go语言规定每个 switch 只能有一个 default 分支。

一分支多值

var a = "mum"
switch a {
case "mum", "daddy":
    fmt.Println("family")
}

不同的 case 表达式使用逗号分隔。

分支表达式

var r int = 11
switch {	//switch后临界大括号
case r > 10 && r < 20:
    fmt.Println(r)
}

注意,这种情况的 switch 后面不再需要跟判断变量。某种程度上已经完全可以替代if-else

跨越 case 的 fallthrough

在Go语言中 case 是一个独立的代码块,执行完毕后不会像C语言那样紧接着执行下一个 case,但是为了兼容一些移植代码,依然加入了 fallthrough 关键字来实现这一功能

var s = "hello"
switch {
case s == "hello":
    fmt.Println("hello")
    fallthrough
case s != "world":
    fmt.Println("world")
}

//输出结果:
//hello
//world

新编写的代码,不建议使用 fallthrough。

4.5 Go语言goto语句——跳转到指定的标签

    err := firstCheckError()
    if err != nil {
        goto onExit
    }
    err = secondCheckError()
    if err != nil {
        goto onExit
    }
    fmt.Println("done")
    return
onExit:
    fmt.Println(err)
    exitProcess()

4.6 Go语言break(跳出循环)

Go语言中 break 语句可以结束 for、switch 和 select 的代码块,另外 break 语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的 for、switch 和 select 的代码块上。

单break的用法也仍然存在。

func main() {
OuterLoop:
    for i := 0; i < 2; i++ {
        for j := 0; j < 5; j++ {
            switch j {
            case 2:
                fmt.Println(i, j)
                break OuterLoop
            case 3:
                fmt.Println(i, j)
                break OuterLoop
            }
        }
    }
}

4.7 Go语言continue(继续下一次循环)

Go语言中 continue 语句可以结束当前循环,开始下一次的循环迭代过程,仅限在 for 循环内使用,在 continue 语句后添加标签时,表示开始标签对应的循环。

单continue的用法也仍然存在。

package main
import "fmt"
func main() {
OuterLoop:
    for i := 0; i < 2; i++ {
        for j := 0; j < 5; j++ {
            switch j {
            case 2:
                fmt.Println(i, j)
                continue OuterLoop
            }
        }
    }
}