Go 学习笔记(9):控制结构

if

else-if 分支的数量是没有限制的,但为了可读性,尽量不要太多。

if condition {
	// do something	
}


if condition {
	// do something	
} else {
	// do something	
}

if condition1 {
	// do something	
} else if condition2 {
	// do something else	
} else {
	// catch-all or default
}
复制代码

注意:else 与前面的 } 必须在同一行:

if x{
}
else {	// 无效的
}
复制代码

switch

switch 的结构相比其它语言更加灵活,可以接受任意形式的表达式

switch var1 {
    case val1:
        ...
    case val2:
        ...
    default:
        ...
}

switch var1 {
    case val1, val2, val3:
        ...
    case val4:
        ...
    default:
        ...
}
复制代码
  • 每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。
  • 一旦成功地匹配到某个分支,执行完相应代码后就会退出整个 switch 代码块。如果还想执行后续代码,可以使用 fallthrough 达到目的。
  • 同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3
  • case ...: 语句之后,不需要使用花括号,可以在分支中进行任意形式的编码。当代码块只有一行时,可以直接放置在 case 语句之后
  • val1val2val3val4 必须是相同的类型,或者最终结果为相同类型的表达式
  • default 分支是可选的,可以出现在任何顺序,但最好将它放在最后

省略判断值

可以不提供任何被判断的值(实际上默认为判断是否为 true),然后在每个 case 分支中进行测试不同的条件。当任一分支的测试结果为 true 时,该分支的代码会被执行。这看起来非常像链式的 if-else 语句,但是在测试条件非常多的情况下,提供了可读性更好的书写方式。

switch {
    case condition1:
        ...
    case condition2:
        ...
    default:
        ...
}


switch {
    case i < 0:
        f1()
    case i == 0:
        f2()
    case i > 0:
        f3()
}
复制代码

初始化语句

switch 语句也可以包含一个初始化语句,这种形式可以非常优雅地进行条件判断

switch initialization {
    case val1:
        ...
    case val2:
        ...
    default:
        ...
}


switch result := calculate(); {
    case result < 0:
        ...
    case result > 0:
        ...
    default:
        // 0
}

// 在下面这个代码片段中,变量 a 和 b 被平行初始化,然后作为判断条件:
switch a, b := x[i], y[j]; {
    case a < b: t = -1
    case a == b: t = 0
    case a > b: t = 1
}
复制代码

fallthrough

如果在执行完每个分支的代码后,还希望继续执行后续分支的代码,可以使用 fallthrough 关键字来达到目的。

func main() {
    i := 0
    switch i {
        case 0: fallthrough
        case 1:
            fmt.Println("111")
            fallthrough
        case 2:
            fmt.Println("222")
        case 3:
            fmt.Println("333")
        default:
            fmt.Println("default")
    }
}
复制代码

type-switch

switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型。

v := 11
switch i := interface{}(v).(type) {
    case int, int8, int16, int32, int64:
        fmt.Printf("A signed integer: %d. The type is %T. \n", i, i)
    case uint, uint8, uint16, uint32, uint64:
        fmt.Printf("A unsigned integer: %d. The type is %T. \n", i, i)
    default:
        fmt.Println("Unknown!")
}
复制代码

for

for 初始化语句; 条件语句; 修饰语句 {}
复制代码
for i := 0; i < 10; i++ {
    fmt.Print(i, " ")
}  

// 错误的代码
for (i := 0; i < 10; i++) {
     fmt.Print(i, " ")
}  

// 使用多个计数器
for i, j := 0, N; i < j; i, j = i+1, j-1 {}

// 嵌套
for i:=0; i<5; i++ {
    for j:=0; j<10; j++ {
        println(j)
    }
}
复制代码

for 经常和 range 搭配使用

select

select 语句属于条件分支流程控制方法,不过它只能用于通道(后面再介绍)。它可以包含若干条 case 语句,case 关键字只能后跟用于通道的发送操作的表达式以及接收操作的表达式或语句。

ch1 := make(chan int, 1)
ch2 := make(chan int, 1)

select {
    case e1 := <-ch1:
        fmt.Printf("1th case is selected. e1=%v.\n", e1)
    case e2 := <-ch2:
        fmt.Printf("2th case is selected. e2=%v.\n", e2)
    default:
        fmt.Println("No data!")
} 
复制代码

break 语句也可以被包含在 select 语句中的 case 语句中。它的作用是立即结束当前的 select 语句的执行,不论其所属的 case 语句中是否还有未被执行的语句。

详细见:www.imooc.com/code/8029

break/continue

break 用来跳出循环,用于任何形式的 for 循环,但在 switchselect 语句中,break 语句的作用结果是跳过整个代码块,执行后续的代码。

break 的作用范围为该语句出现后的最内部的结构,也就是嵌套的循环体中,break 只会退出最内层的循环

continue 只能被用于 for 循环中,作用是忽略剩余的循环体而直接进入下一次循环的过程,但不是无条件执行下一次循环,执行之前依旧需要满足循环的判断条件。

label/goto

forswitchselect 语句都可以配合标签 label 形式的标识符使用,即某一行第一个以冒号(:)结尾的单词(gofmt 会将后续代码自动移至下一行)。

标签的名称是大小写敏感的,为了提升可读性,一般建议使用全部大写字母。

func main() {
    AAA:
        for i := 1; i < 3; i++ {
            fmt.Println("a", i)
            for j := 1; j < 5; j++ {
                fmt.Println("b", j)
                if j == 2 {
                    continue AAA
                }
            }
        }
    
}

// 输出:
a 1
b 1
b 2
a 2
b 1
b 2
复制代码

j==3j==4 时没有输出,因为跳到了 i 的下一次循环。如果将 continue 改成 break,会直接退出外层循环。

使用 goto 语句和标签配合使用来模拟循环

func main() {
    i := 0

    AAA:
        fmt.Println(i)
        i++
        if i == 5 {
            return
        }
        goto AAA
    
}
复制代码

注意:使用标签和 goto 语句是不被鼓励的,它们会很快导致非常糟糕的程序设计,而且总有更加可读的替代方案来实现相同的需求。

如果您必须使用 goto,应当只使用正序的标签(标签位于 goto 语句之后),但注意标签和 goto 语句之间不能出现定义新变量的语句,否则会导致编译失败。

猜你喜欢

转载自blog.csdn.net/weixin_34203426/article/details/88069020