errors是用的最多的一个package,go doc上面显示有202948个package使用了errors。我相信只有使用go写程序,基本上都会用到这个库。每一个编程语言都离不开错误处理的话题。
Java 通过catch…exception结构来处理错误。
C语言通过函数返回值,来表示函数执行情况。默认是返回0,表示成功,非0表示失败。
Go 同样通过函数返回值来表示函数的执行情况。Nil表示函数执行成功,非nil表示函数执行失败。
那么go如何表示应用程序的错误,这其实就是errors库的作用。这里我们假设一个函数的定义如下:
-
func TestFunc(a int) (int, error)
我们看返回值部分,他返回两部分,一部分是函数的返回值,另一个是函数的错误。这里我们假设函数按预期执行返回nil,出现问题返回非nil。那么非nil怎么表示?这个非nil其实我们有以下要求:
-
能够明确说明函数执行碰到了什么问题。
-
可以与nil做比较。
首先我们看error到底是个什么东西?
-
type error interface {
-
Error() string
-
}
它其实是一个接口类型,要求是要实现Error()string 方法。
标准库介绍里只提到了New函数,
他返回一个errorString结构体的指针,这个类型实现了Error方法。这一个函数就可以让我们轻松面对我们的日常开发。
-
type errorString struct {
-
s string
-
err error
-
frame Frame
-
}
-
func (e *errorString) Error() string {
-
if e.err != nil {
-
return e.s + ": " + e.err.Error()
-
}
-
return e.s //自定义的会返回这个
-
}
-
func New(text string) error {
-
// Inline call to errors.Callers to improve performance.
-
var s Frame
-
runtime.Callers(2, s.frames[:])
-
return &errorString{text, nil, s}//自定义的err总为nil
-
}
生成error的方式
1. 自定义类型,实现Error方法
-
mkdir -p $GOPATH/src/github.com/errors-example
-
cd $GOPATH/src/github.com/errors-example
-
touch errorsExample.go
-
package main
-
-
import (
-
"fmt"
-
"time"
-
)
-
-
type MyError struct {
-
When time.Time
-
What string
-
}
-
-
func (e *MyError) Error() string {
-
return fmt.Sprintf("%v:%v", e.When, e.What)
-
}
-
-
func oops() error {
-
return &MyError{
-
time.Date(1989, 3, 15, 22, 30, 0, 0, time.UTC),
-
"the file system has gone away",
-
}
-
}
-
func main() {
-
if err := oops(); err != nil {
-
fmt.Println(err)
-
}
-
}
这里定义了一个结构体MyError,包涵一个时间,一个字符串,实现了Error方法,返回时间戳和字符串。 那么它符合error接口的定义,所以可以是一个error。
2. 使用New函数,生成标准error
-
err := errors.New("emit macho dwarf: elf header corrupted")
-
if err != nil {
-
fmt.Print(err)
-
}
3. 使用fmt包中的Errorf生成error
-
const name, id = "bimmler", 17
-
err := fmt.Errorf("user %q (id %d) not found", name, id)
-
if err != nil {
-
fmt.Print(err)
-
}
总结:合适的错误定义,可以使我们的思路和代码清晰。
阅读(7453) | 评论(0) | 转发(0) |