Files
the-way-to-go_ZH_CN/eBook/17.1.md
Haigang Zhou fa1cfcc67f 第十七十八章 (#833)
Co-authored-by: Joe Chen <jc@unknwon.io>
2022-05-19 19:57:23 +08:00

82 lines
2.2 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 个参数时使用这种模式:`something, 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.2(4) 小节](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)