/errors

go errors

Primary LanguageGoMIT LicenseMIT

使用例子

错误记录器

本设计补充并实现了系统的error接口,

用于发生错误时附带发生错误的原因、位置等信息以便还原现场。

因本错误设计含有比较大的数据量信息,因此需要注意被调用的频率,以避免影响到系统效率。

  • 使用例子
package main

import "github.com/gwaylib/errors"

func fn1(a int) error {
   if a == 1{
       return errors.ErrNoData.As(a)
   }
   return errors.New("not implements").As(a)
}

func fn2(b int) error {
   return errors.As(fn1(b))
}

func main() {
   err := fn2(2)
   if err != nil {
 	  // 注意,errors.ErrNoData == err 会不一定成立, 需要使用Equal方法
       if !errors.ErrNoData.Equal(err) {
           panic(err)
       }
       // 处理错误码相等的情况
       fmt.Println(err)
   }
}
  • 输出用例解读
输出:
{"Err":"test","As":[["errors.TestError(errors_test.go:113)","[init]"],["errors.TestError(errors_test.go:118)","[123 456]"]]}

Err -- errors.New()输入的Code值

As 
    -- ["errors.TestError(errors_test.go:113)","init"] 第一次被As调用记录的内容(初始化实例时第一次自动被调用)
        -- "errors.TestError(errors_test.go:113)" 第一次被As调用的位置信息
           -- errors.TestError 被调用了errors.As的函数 
           -- (errors_test.go:113) 被调用的文件行数
       -- "init" errors.As输入的所记录的第一个参数

    -- ["errors.TestError(errors_test.go:118)",123,456]] 第二次被As调用记录的内容
       -- "errors.TestError(errors_test.go:118)" 第二次被As调用的位置信息
            -- errors.TestError 被调用了errors.As的函数 
            -- (errors_test.go:118) 被调用的文件行数
       -- 123 errors.As输入的所记录的第一个参数
       -- 456 errors.As输入的所记录的第二个参数
       

GO错误处理建议

  • 优先处理错误,再处理正常逻辑, 错误将不容易被忽略。
// 建议写法
rows, err := db.Query(...)
if err != nil{
    return errors.As(err)
}
defer rows.Close()
...

// 不建议写法
rows, err := db.Query(...)
if err == nil{
    defer rows.Close()
    // ...
} else {
    // 处理错误,或不处理错误
}
  • 异常逻辑应尽快结束返回,结束函数流程,而不应再执行逻辑。

  • 正常逻辑尽可能不放在if中,以使正常逻辑不缩进以便阅读。

// 除非必要,不建议使用此种错误类别的定义, 它易将错误定义发散到整个函数而失去可控性
func Get() (err error){
    defer func(){
        if err != nil{
            // 处理错误
        }
    }()

    // ...
}
  • 除非明确了处理结果,否则错误应总是向上返回给调用者;
  • 除非明确了处理结果,调用者不应丢弃任何错误, 应给出用户提示或记录日志,以便完整知道系统发生了什么。