Comment on page

18 错误处理

错误处理基本用法:
package main
import (
"fmt"
"math"
)
func sqrt(n float64) (float64, error) {
if n < 0 {
return 0, fmt.Errorf("invalid argument '%f', must be >= 0", n)
}
return math.Sqrt(n), nil
}
func printSqrt(n float64) {
if res, err := sqrt(n); err == nil {
fmt.Printf("sqrt of %f is %f\n", n, res)
} else {
fmt.Printf("sqrt of %f returned error '%s'\n", n, err)
}
}
func main() {
printSqrt(16)
printSqrt(-16)
}
// 输出结果
// sqrt of 16.000000 is 4.000000
// sqrt of -16.000000 returned error 'invalid argument '-16.000000', must be >= 0'
跟C#和Python不同,Go的错误处理是直接返回错误值,而不是抛出异常。
Go也提供了恐慌和恢复的异常机制,但它们应该被尽量少用。
错误也是值,就像整数或字符串一样。
error类型是一个内置(built-in)接口类型,该接口规定了Error() string方法。
如果要表示执行成功,则把表示错误的变量置为nil返回。
若要表示执行失败,则把错误变量赋值为errors.New(msg string)fmt.Errorf(format string, args... interface{})返回的值。
您也可以通过自定义一个结构体并实现Error() string方法来自定义错误类型
如果一个函数要返回错误,那么错误值应当总是最后一个。
应始终检查函数的返回值中是否包含错误。编写鲁棒性强的软件的关键就是检查错误并进行适当处理。初学者通常放弃检查错误,然后面临调试神秘故障的麻烦。

译者注:error源码解读

// error接口的定义
// src/builtin/builtin.go
type error interface {
Error() string
}
// error的实现
// src/errors/errors.go
// New returns an error that formats as the given text.
// Each call to New returns a distinct error value even if the text is identical.
func New(text string) error {
return &errorString{text}
}
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
就这么多,没了。是不是简单到爆。error仅仅是一种普通的interface类型,包含一个返回类型为字符串的Error()函数。