## 5.6\. 控制流
Go语言的控制结构与C的基本相同但是有些地方还是不同。Go中没有do, while这样的循环,for与switch 也非常的灵活。if和switch可以有一个初始化语句 就像for一样。还增加了一个type switch(类型选择)和多通道复用(multiway communications multiplexer)的select. 语法有一点点区别,圆括号大部分是 不需要的但是大括号必须始终括号分隔.
### 5.6.1\. If
Go中简单的if实例:
```
if x > 0 {
return y
}
```
建议在写if语句的时候采用多行。这是一种非常好的编程风格, 特别是在控制结构体里面有return或break的时候.
if和switch允许初始化声明,就可以使用本地变量(local variable).
```
if err := file.Chmod(0664); err != nil {
log.Stderr(err)
return err
}
```
在Go的库文件中,你可能经常看到if语句不进入下一条语句是因为函数在 break,continue,goto或reurn结束, else可以省略。
```
f, err := os.Open(name, os.O_RDONLY, 0)
if err != nil {
return err
}
codeUsing(f)
```
一般的代码都会考虑错误的处理,如果没有出错的情况就继续运行但是在出错的时候 函数就会返回,所以在这里不需要else语句。
```
f, err := os.Open(name, os.O_RDONLY, 0)
if err != nil {
return err
}
d, err := f.Stat()
if err != nil {
return err
}
codeUsing(f, d)
```
### 5.6.2\. For
Go中的for循环与C相似,但是也有不同的地方。Go只有for和 while, 没有do-while语句。这里有三种方式,只有一种方式 使用了分号。
```
// Like a C for
for init; condition; post { }
// Like a C while
for condition { }
// Like a C for(;;)
for { }
```
短声明使得在循环里声明下标变量很容易。
```
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
```
如果你要遍历一个array, slice, string or map or 从通道(channel)读数 range将是你最好的选择。
```
var m map[string]int
sum := 0
for _, value := range m { // key is unused
sum += value
}
```
对于字符串,range能为你更好的工作,比如解析UTF-8并单独输出Unicode字符.
```
for pos, char := range "日本語" {
fmt.Printf("character %c starts at byte position %d\n", char, pos)
}
```
打印出:
```
character 日 starts at byte position 0
character 本 starts at byte position 3
character 語 starts at byte position 6
```
最后,Go中没有逗号运算符(comma operator)和++与--运算, 如果你想执行多个变量在for语句中,你可以使用并行参数(parallel assignment).
```
// Reverse a
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
a[i], a[j] = a[j], a[i]
}
```
### 5.6.3\. Switch
Go中的switch要比C更全面,C的表达式仅仅只有常数或整数。 每个分支(cases)从上到下进行匹配取值, 如果switch没有表达式 那么switches是真。所有才有可能使用switch替换
```
func unhex(c byte) byte {
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
return 0
}
```
没有自动掉到下一分支,但分支可以是逗号分隔的列表:
```
func shouldEscape(c byte) bool {
switch c {
case ' ', '?', '&', '=', '#', '+', '%':
return true
}
return false
}
```
这个操作数组的程序和上面的相似是通过两个switch语句。
```
// Compare returns an integer comparing the two byte arrays
// lexicographically.
// The result will be 0 if a == b, -1 if a < b, and +1 if a > b
func Compare(a, b []byte) int {
for i := 0; i < len(a) && i < len(b); i++ {
switch {
case a[i] > b[i]:
return 1
case a[i] < b[i]:
return -1
}
}
switch {
case len(a) < len(b):
return -1
case len(a) > len(b):
return 1
}
return 0
}
```
switch可以动态的取得接口变量的数据类型,比如: type switch就是 用关键字type插入到接口类型后面的括号来判断类型, 如果switch 在表达式中声明了一个变量,在分支上就有相应的类型。
```
switch t := interfaceValue.(type) {
default:
fmt.Printf("unexpected type %T", t) // %T prints type
case bool:
fmt.Printf("boolean %t\n", t)
case int:
fmt.Printf("integer %d\n", t)
case *bool:
fmt.Printf("pointer to boolean %t\n", *t)
case *int:
fmt.Printf("pointer to integer %d\n", *t)
}
```
- 1. 关于本文
- 2. Go语言简介
- 3. 安装go环境
- 3.1. 简介
- 3.2. 安装C语言工具
- 3.3. 安装Mercurial
- 3.4. 获取代码
- 3.5. 安装Go
- 3.6. 编写程序
- 3.7. 进一步学习
- 3.8. 更新go到新版本
- 3.9. 社区资源
- 3.10. 环境变量
- 4. Go语言入门
- 4.1. 简介
- 4.2. Hello,世界
- 4.3. 分号(Semicolons)
- 4.4. 编译
- 4.5. Echo
- 4.6. 类型简介
- 4.7. 申请内存
- 4.8. 常量
- 4.9. I/O包
- 4.10. Rotting cats
- 4.11. Sorting
- 4.12. 打印输出
- 4.13. 生成素数
- 4.14. Multiplexing
- 5. Effective Go
- 5.1. 简介
- 5.2. 格式化
- 5.3. 注释
- 5.4. 命名
- 5.5. 分号
- 5.6. 控制流
- 5.7. 函数
- 5.8. 数据
- 5.9. 初始化
- 5.10. 方法
- 5.11. 接口和其他类型
- 5.12. 内置
- 5.13. 并发
- 5.14. 错误处理
- 5.15. Web服务器
- 6. 如何编写Go程序
- 6.1. 简介
- 6.2. 社区资源
- 6.3. 新建一个包
- 6.4. 测试
- 6.5. 一个带测试的演示包
- 7. Codelab: 编写Web程序
- 7.1. 简介
- 7.2. 开始
- 7.3. 数据结构
- 7.4. 使用http包
- 7.5. 基于http提供wiki页面
- 7.6. 编辑页面
- 7.7. template包
- 7.8. 处理不存在的页面
- 7.9. 储存页面
- 7.10. 错误处理
- 7.11. 模板缓存
- 7.12. 验证
- 7.13. 函数文本和闭包
- 7.14. 试试!
- 7.15. 其他任务
- 8. 针对C++程序员指南
- 8.1. 概念差异
- 8.2. 语法
- 8.3. 常量
- 8.4. Slices(切片)
- 8.5. 构造值对象
- 8.6. Interfaces(接口)
- 8.7. Goroutines
- 8.8. Channels(管道)
- 9. 内存模型
- 9.1. 简介
- 9.2. Happens Before
- 9.3. 同步(Synchronization)
- 9.4. 错误的同步方式
- 10. 附录
- 10.1. 命令行工具
- 10.2. 视频和讲座
- 10.3. Release History
- 10.4. Go Roadmap
- 10.5. 相关资源