对于函数的返回值,惯例是最后一个参数返回error对象,来表示函数运行的状态。
如:
- n, err := func()
- if err != nil {
- ...//process error
- }
- if n, err := func(); err != nil {
- ...//process error
- }
error对象可以由errors.New()或fmt.Errorf()构造。
如:
- var dividedErr = errors.New("Cant divided by 0")
- err := fmt.Errorf("%d cant divided by 0", arg)
我们先来看看error到底是什么类型。
error在标准库中被定义为一个接口类型,该接口只有一个Error()方法:
- type error interface {
- Error() string
- }
我们可以创建一个结构体,并实现Error()方法,就能根据自己的意愿构造error对象了。
如:
- type division struct {
- arg int
- str string
- }
- func (e *division) Error() string {
- return fmt.Sprintf("%d %s", e.arg, e.str)
- }
- func divideCheck(arg1, arg2 int) (error) {
- if arg2 == 0 {
- return &division{arg1, "can't divided by 0"}
- }
- return nil
- }
再来看一个例子,检查一组数据中是否有不能除(即除数为0)的情况,如果有则返回出错。
代码如下:
- package main
- import "fmt"
- func divideCheck(arg1, arg2 int) (error) {
- if arg2 == 0 {
- return fmt.Errorf("%d can't divided by 0", arg1)
- }
- return nil
- }
- func main() {
- var err error
- err = divideCheck(4, 2)
- if err != nil {
- fmt.Println(err)
- return
- }
- err = divideCheck(8, 0)
- if err != nil {
- fmt.Println(err)
- return
- }
- }
我们实现了这个功能,但是这样的代码非常不优雅,每执行一次函数调用都至少要用3行来做错误处理。
下面来优化一下。我们需要实现的功能是,只要有一个数不能除,就返回出错。那么只需要把每次检查后的状态存储到内部状态变量里,在全部处理完成后再检查这个变量就行了。
代码如下:
- package main
- import "fmt"
- type division struct {
- err error
- }
- func (this *division)DivideCheck(arg1, arg2 int) {
- if this.err != nil {
- return
- }
- if arg2 == 0 {
- this.err = fmt.Errorf("%d can't divided by 0", arg1)
- return
- }
- }
- func (this *division)Err() error {
- return this.err
- }
- func main() {
- d := new(division)
- d.DivideCheck(4, 2)
- d.DivideCheck(8, 0)
- if d.Err() != nil {
- fmt.Println(d.Err())
- }
- }
golang的错误处理是经常被诟病的地方,但如果懂得以go的方式编程,还是可以做的挺优雅的~