ArcherWong博客
首页
博客
golang笔记---控制结构
作者:ArcherWong
分类:golang
时间:2019-01-04 10:34:24
阅读:389
[TOC] # if-else 结构 ``` 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 } ``` 关键字 if 和 else 之后的左大括号 `{` 必须和关键字在同一行,如果你使用了 else-if 结构,则前段代码块的右大括号 `}` 必须和 else-if 关键字在同一行。这两条规则都是被编译器强制规定的。 实例:判断一个字符串是否为空: ``` if str == "" { ... } if len(str) == 0 {...} ``` if 可以包含一个初始化语句(如:给一个变量赋值)。这种写法具有固定的格式(在初始化语句后方必须加上分号): ``` if initialization; condition { // do something } ``` 例如: ``` val := 10 if val > max { // do something } ``` 你也可以这样写: ``` if val := 10; val > max { // do something } ``` 但要注意的是,使用简短方式 := 声明的变量的作用域只存在于 if 结构中(在 if 结构的大括号之间,如果使用 if-else 结构则在 else 代码块中变量也会存在)。 如果变量在 if 结构之前就已经存在,那么在 if 结构中,该变量原来的值会被隐藏。最简单的解决方案就是不要在初始化语句中声明变量 示例 ifelse.go ``` package main import "fmt" func main() { var cond int if cond = 5; cond > 10 { fmt.Printf("cond is greater than 10\n") } else { fmt.Printf("cond is not greater than 10\n") } } ``` 输出: ``` cond is not greater than 10 ``` # switch 结构 ``` switch var1 { case val1: ... case val2: ... default: ... } ``` **变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值**。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。**前花括号 { 必须和 switch 关键字在同一行**。 您可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:`case val1, val2, val3`。 每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。一旦成功地匹配到某个分支,在执行完相应代码后就会退出整个 switch 代码块,也就是说您**不需要特别使用 break 语句来表示结束**。 因此,程序也不会自动地去执行下一个分支的代码。如果在执行完每个分支的代码后,还希望继续执行后续分支的代码,可以使用 `fallthrough` 关键字来达到目的。 因此: ``` switch i { case 0: // 空分支,只有当 i == 0 时才会进入分支 case 1: f() // 当 i == 0 时函数不会被调用 } ``` 并且: ``` switch i { case 0: fallthrough case 1: f() // 当 i == 0 时函数也会被调用 } ``` 可以使用 return 语句来提前结束代码块的执行。当您在 switch 语句块中使用 return 语句,并且您的函数是有返回值的,您还需要在 switch 之后添加相应的 return 语句以确保函数始终会返回。 # for 结构 ## 基于计数器的迭代 文件 for1.go 中演示了最简单的基于计数器的迭代,基本形式为: ``` for 初始化语句; 条件语句; 修饰语句 {} ``` 示例 5.6 for1.go: ``` package main import "fmt" func main() { for i := 0; i < 5; i++ { fmt.Printf("This is the %d iteration\n", i) } } ``` 输出: ``` This is the 0 iteration This is the 1 iteration This is the 2 iteration This is the 3 iteration This is the 4 iteration ``` 循环的头部由三部分组成,它们之间使用分号 ; 相隔,**但并不需要括号 () 将它们括起来**。例如:for (i = 0; i < 10; i++) { },这是无效的代码!同样的,左花括号 { 必须和 for 语句在同一行,计数器的生命周期在遇到右花括号 } 时便终止。 两个 for 循环嵌套起来: ``` for i:=0; i<5; i++ { for j:=0; j<10; j++ { println(j) } } ``` ## 基于条件判断的迭代 for 结构的第二种形式是没有头部的条件判断迭代(类似其它语言中的 while 循环),基本形式为:for 条件语句 {}。 ``` package main import "fmt" func main() { var i int = 5 for i >= 0 { i = i - 1 fmt.Printf("The variable i is now: %d\n", i) } } ``` 输出: ``` The variable i is now: 4 The variable i is now: 3 The variable i is now: 2 The variable i is now: 1 The variable i is now: 0 The variable i is now: -1 ``` ## 无限循环 条件语句是可以被省略的,如 `i:=0; ; i++` 或 `for { }` 或 `for ;; { }` `;;` 会在使用 gofmt 时被移除这些循环的本质就是无限循环。最后一个形式也可以被改写为 for true { },但一般情况下都会直接写 for { }。 如果 for 循环的头部没有条件语句,那么就会认为条件永远为 true,因此循环体内必须有相关的条件判断以确保会在某个时刻退出循环。 想要直接退出循环体,可以使用 break 语句或 return 语句直接返回。 但这两者之间有所区别,**break 只是退出当前的循环体,而 return 语句提前对函数进行返回,不会执行后续的代码**。 ## For-range结构 可以迭代任何一个集合,可以应用于数组和切片等 ``` for ix, value := range slice1 { ... } ``` 第一个返回值 ix 是数组或者切片的索引,第二个是在该索引位置的值;他们都是仅在 for 循环内部可见的**局部变量**。**value 只是 slice1 某个索引位置的值的一个拷贝**,不能用来修改 slice1 该索引位置的值。 示例 7.9 slices_forrange.go ``` package main import "fmt" func main() { var slice1 []int = make([]int, 4) slice1[0] = 1 slice1[1] = 2 slice1[2] = 3 slice1[3] = 4 for ix, value := range slice1 { fmt.Printf("Slice at %d is: %d\n", ix, value) } } ``` 结果: ``` Slice at 0 is: 1 Slice at 1 is: 2 Slice at 2 is: 3 Slice at 3 is: 4 ``` # beark 和 continue break 语句的作用结果是跳过整个代码块,执行后续的代码,**break 只会退出最内层的循环**: 示例 for4.go: ``` package main func main() { for i:=0; i<3; i++ { for j:=0; j<10; j++ { if j>5 { break } print(j) } print(" ") } } ``` 输出: ``` 012345 012345 012345 ``` 关键字 continue 忽略剩余的循环体而**直接进入下一次循环的过程**,但不是无条件执行下一次循环,执行之前依旧需要满足循环的判断条件。 示例 for5.go: ``` package main func main() { for i := 0; i < 10; i++ { if i == 5 { continue } print(i) print(" ") } } ``` 输出: ``` 0 1 2 3 4 6 7 8 9 ``` 显然,5 被跳过了。 另外,**关键字 continue 只能被用于 for 循环中**。 # 标签与goto for、switch 或 select 语句都可以配合标签(label)形式的标识符使用,即某一行第一个以冒号(:)结尾的单词(gofmt 会将后续代码自动移至下一行)。 标签的名称是大小写敏感的,为了提升可读性,**一般建议使用全部大写字母** ``` package main import "fmt" func main() { LABEL1: for i := 0; i <= 5; i++ { for j := 0; j <= 5; j++ { if j == 4 { continue LABEL1 } fmt.Printf("i is: %d, and j is: %d\n", i, j) } } } ``` 本例中,continue 语句指向 LABEL1,当执行到该语句的时候,就会跳转到 LABEL1 标签的位置。 您可以看到当 j==4 和 j==5 的时候,没有任何输出:标签的作用对象为外部循环,因此 i 会直接变成下一个循环的值,而此时 j 的值就被重设为 0,即它的初始值。如果将 continue 改为 break,则不会只退出内层循环,而是直接退出外层循环了。 另外,还可以使用 goto 语句和标签配合使用来模拟循环。 示例 5.14 goto.go: ``` package main func main() { i:=0 HERE: print(i) i++ if i==5 { return } goto HERE } ``` 上面的代码会输出 01234。 使用逆向的 goto 会很快导致意大利面条式的代码,所以不应当使用而选择更好的替代方案。 **特别注意: 使用标签和 goto 语句是不被鼓励的**:它们会很快导致非常糟糕的程序设计,而且总有更加可读的替代方案来实现相同的需求。 **参考资料** https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/directory.md
标签:
上一篇:
golang笔记---结构(struct)和方法(method)
下一篇:
golang笔记---数组(array)和切片(slice)
文章分类
css
elasticsearch
git
golang
guacamole
javascript
letsencrypt
linux
nginx
other
php
python
vue
web
阅读排行
centos7.3配置guacamole
golang笔记---关联数组(map)
letsencrypt证书-管理工具certbot
golang笔记---template模板语法
详解网络连接
友情链接
node文件
laravel-vue
ArcherWong的博客园