Files
the-way-to-go_ZH_CN/eBook/17.1.md
marjune 9be772e9bb Add chapter 17.x (#697)
* improve chapter 15.12

* add chapter 17.2

* add chapter 17.3

* add chapter 17.4
2019-07-27 19:26:44 -07:00

82 lines
2.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 17.1 逗号 ok 模式
在学习本书第二部分和第三部分时我们经常在一个表达式返回2个参数时使用这种模式`,ok`,第一个参数是一个值或者`nil`,第二个参数是`true`/`false`或者一个错误`error`。在一个需要赋值的`if`条件语句中使用这种模式去检测第二个参数值会让代码显得优雅简洁。这种模式在go语言编码规范中非常重要。下面总结了所有使用这种模式的例子
1在函数返回时检测错误参考[第5.2小节](05.2.md):
```go
value, err := pack1.Func1(param1)
if err != nil {
fmt.Printf("Error %s in pack1.Func1 with parameter %v", err.Error(), param1)
return err
}
// 函数Func1没有错误:
Process(value)
e.g.: os.Open(file) strconv.Atoi(str)
```
这段代码中的函数将错误返回给它的调用者,当函数执行成功时,返回的错误是`nil`,所以使用这种写法:
```go
func SomeFunc() error {
if value, err := pack1.Func1(param1); err != nil {
return err
}
return nil
}
```
这种模式也常用于通过`defer`使程序从`panic`中恢复执行(参考[第17.24小节](17.2.md))。
要实现简洁的错误检测代码,更好的方式是使用闭包,参考[第16.10.2小节](16.10.md)
2检测映射中是否存在一个键值参考[第8.2小节](08.2.md)`key1`在映射`map1`中是否有值?
```go
if value, isPresent = map1[key1]; isPresent {
Process(value)
}
// key1不存在
```
3检测一个接口类型变量`varI`是否包含了类型`T`:类型断言(参考[第11.3小节](11.3.md)
```go
if value, ok := varI.(T); ok {
Process(value)
}
// 接口类型varI没有包含类型T
```
4检测一个通道`ch`是否关闭(参考[第14.3小节](14.3.md)
```go
for input := range ch {
Process(input)
}
```
或者:
```go
for {
if input, open := <-ch; !open {
break // 通道是关闭的
}
Process(input)
}
```
## 链接
- [目录](directory.md)
- 上一节:[Go 语言模式](17.0.md)
- 下一节:[defer 模式](17.2.md)