Go 常见的错误处理方式

一、Go 处理错误的三种方式

1、经典Go逻辑

// ZooTour1 struct
type ZooTour1 interface {
    Enter() error 
    VisitPanda(panda *Panda) error 
    VisitTiger(tiger *Tiger) error
    Leave() error
}

// 分步处理,每个步骤可以针对具体返回结果进行处理
func Tour1(t ZooTour1, panda *Panda, tiger *Tiger) error {
    if err := t.Enter(); err != nil {
        return errors.WithMessage(err, "Enter failed.")
    }
    if err := t.VisitPanda(panda); err != nil {
        return errors.WithMessage(err, "VisitPanda failed.")
    }
    if err := t.VisitTiger(tiger); err != nil {
        return errors.WithMessage(err, "VisitTiger failed.")
    }
    if err := t.Leave(); err != nil {
        return errors.WithMessage(err, "Leave failed.")
    }

    return nil
}

2. 屏蔽过程中的error的处理

将error保存到对象内部,处理逻辑交给每个方法,本质上仍是顺序执行。标准库中的buffio.Scanner 就是这个方式实现的。

// ZooTour2
type ZooTour2 interface {
    Enter() error
    VisitPanda(panda *Panda) error
    VisitTiger(tiger *Tiger) error
    Leave() error

    Err() error
}

// Tour2 func
func Tour2(t ZooTour2, panda *Panda, tiger *Tiger) error {

    t.Enter()
    t.VisitPanda(panda)
    t.VisitTiger(tiger)
    t.Leave()
    
   // 集中编写业务逻辑代码,最后统一处理error
    if err := t.Err(); err != nil {
        return errors.WithMessage(err, "ZooTour failed")
    }
    return nil
}

// VisitPanda
func (t *myZooTour) VisitPanda(panda *Panda) {
    if t.err != nil {
        return
    }

    // ...
}

3. 利用函数式编程延迟运行

分离关注点 - 遍历访问用数据结构定义运行顺序,根据场景选择,如顺序、逆序、二叉树树遍历等。kubernetes中的visitor对此就有很多种扩展方式,分离了数据和行为,有兴趣可以去扩展阅读

type Walker interface {
    Next MyFunc
}

// 一个简单的切片walker
type SliceWalker struct {
    index int 
    funs []MyFunc
} 

type MyFunc func(t ZooTour1) error 

func NewEnterFunc() MyFunc {
    return func(t ZooTour1) error {
        return t.Enter()
    }
}

func BreakOnError(t ZooTour1, walker Walker) error {
    for {
        f := walker.Next() 
        if f == nil {
            break
        }
        if err := f(t); err := nil {
          // break  
      }
    }
}

二、三种方式对比

上面这三个例子,是Go项目处理错误使用频率最高的三种方式,也可以应用在error以外的处理逻辑。 你对这三种方式有什么个人理解,能否分享一下 你对go语言error处理心得呢?也可以聊聊,在特定的业务场景,你以为这三种代码分格的存在的利与弊。

case 1: 如果业务逻辑不是很清楚,比较推荐case1。


image.png

case 2: 很少代码去修改,类似标准库,可以使用case2。


image.png

case 3: 非常复杂的场景,复杂到抽象成一种设计模式。


image.png

参考文档:

https://github.com/Junedayday/code_reading

你可能感兴趣的:(Go 常见的错误处理方式)