## 啊哦,亲,你看得也太快了。。。还没翻译完呢 0 0 要不等到 **2014 年 4 月 10 日** 再来看看吧~~ 这里还有一些其它的学习资源噢~ - [《Go编程基础》](https://github.com/Unknwon/go-fundamental-programming) - [《Go Web编程》](https://github.com/astaxie/build-web-application-with-golang) - [《Go名库讲解》](https://github.com/Unknwon/go-rock-libraries-showcases) 神马?你说你不想学习?那好吧,去逛逛看看行情也行~ - [Go Walker](https://gowalker.org) **Go 项目 API 文档在线浏览工具** - [Go 中国社区](http://bbs.go-china.org) - [Go语言学习园地](http://studygolang.com/) - [Golang中国](http://golang.tc) # 5.2 测试多返回值函数的错误 Go 语言的函数经常使用两个返回值来表示执行是否成功:返回某个值以及 true 表示成功;返回零值(或 nil)和 false 表示失败(第 4.4 节)。当不使用 true 或 false 的时候,也可以使用一个 error 类型的变量来代替作为第二个返回值:成功执行的话,error 的值为 nil,否则就会包含相应的错误信息(Go 语言中的错误类型为 error: `var err error`,我们将会在第 13 章进行更多地讨论)。这样一来,就很明显需要用一个 if 语句来测试执行结果;由于其符号的原因,这样的形式又称之为 comma,ok 模式(pattern)。 在第 4.7 节的程序 `string_conversion.go` 中,函数 `strconv.Atoi` 的作用是将一个字符串转换为一个整数。之前我们忽略了相关的错误检查: anInt, _ = strconv.Atoi(origStr) 如果 origStr 不能被转换为整数,anInt 的值会变成 0 而 `_` 无视了错误,程序会继续运行。 这样做是非常不好的:程序应该在最接近的位置检查所有相关的错误,至少需要暗示用户有错误发生并对函数进行返回,甚至中断程序。 我们在第二个版本中对代码进行了改进: 示例 1: Example 5.3 [string_conversion2.go](examples/chapter_5/string_conversion2.go) package main import ( "fmt" "strconv" ) func main() { var orig string = "ABC" // var an int var newS string // var err error fmt.Printf("The size of ints is: %d\n", strconv.IntSize) // anInt, err = strconv.Atoi(origStr) an, err := strconv.Atoi(orig) if err != nil { fmt.Printf("orig %s is not an integer - exiting with error\n", orig) return } fmt.Printf("The integer is %d\n", an) an = an + 5 newS = strconv.Itoa(an) fmt.Printf("The new string is: %s\n", newS) } 这是测试 err 变量是否包含一个真正的错误(`if err != nil`)的习惯用法。如果确实存在错误,则会打印相应的错误信息然后通过 return 提前结束函数的执行。我们还可以使用携带返回值的 return 形式,例如 `return err`。这样一来,函数的调用者就可以检查函数执行过程中是否存在错误了。 **习惯用法** value, err := pack1.Function1(param1) if err!=nil { fmt.Printf("An error occured in pack1.Function1 with parameter %v", param1) return err } // 未发生错误,继续执行: 由于本例的函数调用者属于 main 函数,所以程序会直接停止运行。 如果我们想要在错误发生的同时终止程序的运行,我们可以使用 `os` 包的 `Exit` 函数: **习惯用法** if err !=nil { fmt.Printf("Program stopping with error %v", err) os.Exit(1) } (此处的退出代码 1 可以使用外部脚本获取到) 有时候,你会发现这种习惯用法被连续重复地使用在某段代码中。 当没有错误发生时,代码继续运行就是唯一要做的事情,所以 if 语句块后面不需要使用 else 分支。 示例 2:我们尝试通过 `os.Open` 方法打开一个名为 `name` 的只读文件: f, err := os.Open(name) if err !=nil { return err } doSomething(f) // 当没有错误发生时,文件对象被传入到某个函数中 doSomething **练习 5.1** 尝试改写 [string_conversion2.go](examples/chapter_5/string_conversion2.go) 中的代码,要求使用 `:=` 方法来对 err 进行赋值,哪些地方可以被修改? 示例 3: ## 链接 - [目录](directory.md) - 上一节:[if-else 结构](05.1.md) - 下一节:[switch 结构](05.3.md)