基于golang实现的error工具包

本文介绍了一款针对Go语言开发的错误处理工具包,它能够帮助开发者更快速地定位错误并提供详细的堆栈信息。通过Err和Errf函数记录错误,并可通过StackTrace函数获取错误位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面的话

最近在开发Go项目,发现Go语言本身存在的error并没有像触发panic时显示详细的调试信息。对于复杂的系统而言,这会让我们开发者需要一定的时间才能定位到错误。所以我们基本Go本身的error封装了一个可以快速定位错误工具包。下面让我们来看看这个工具包是怎么实现的。

设计思想

  1. 工具包提供ErrErrf两个完善来登记错误,其用法分别类似于fmt.Printfmt.Printf的使用方式,在参数的定义中添加了innerError参数来实现错误的传递,其值可为nil.
  2. 对外提供StackTrace函数,方便使用者获取错误产生的堆栈信息。
  3. 通过SetConfig方式实现对错误信息显示的配置,如在生产环境不需要打印堆栈信息。通过响应的配置即可关闭。

实现思路

工具包中主要是对堆栈信息的处理,就是如何才能定位到error的产生位置,通过查看官方文档,我们发现通过runtime包中的CallersCallersFrames函数可以获取当前函数调用的堆栈信息。并且通过Skip参数和自定义过滤条件即可拿到error的产生位置。具体的实现过程如下:

对外提供的2个函数的实现
type Error struct {
    err     error
    msg     string
    fullMsg string
    stackTrace
}

func Errf(err error, format string, args ...interface{}) *Error {
    e := &Error{
        err: err,
        msg: fmt.Sprintf(format, args),
    }
    e.fullMsg = e.genFullMsg()
    return e
}

func Err(err error, args ...interface{}) *Error {
    e := &Error{
        err: err,
        msg: fmt.Sprint(args),
    }
    e.fullMsg = e.genFullMsg()
    return e
}
堆栈信息的实现
type stackTrace struct {
    // stack info
    data    string
    callers []uintptr
}

func (err *Error) getStackTrace() string {
    if strings.TrimSpace(err.data) == "" {
        return err.genStackTrace(5)
    }
    return err.data
}

func (err *Error) StackTrace() string {
    return err.data
}

func (err *Error) genStackTrace(skip int) string {
    if config.isPrintStack == 1 {
        var buffer bytes.Buffer
        buffer.WriteString("StackTrace:\n")
        var st [64]uintptr
        n := runtime.Callers(skip, st[:])
        err.callers = st[:n]
        frames := runtime.CallersFrames(err.callers)
        for {
            frame, ok := frames.Next()
            if !ok {
                break
            }
            if !strings.Contains(frame.File, "runtime/") {
                buffer.WriteString(fmt.Sprintf("%s\n\t%s:%d\n", 
                frame.Func.Name(), frame.File, frame.Line))
            }
        }
        err.data = buffer.String()
        return err.data
    }
    return ""
}
错误信息显示配置的实现
const (
    //print stack info
    PRINTSTACK = 1
)

// global error config object
var config *errConfig = &errConfig{}

// error config
type errConfig struct {
    isPrintStack uint32
}

//set error config info
func SetConfig(conf byte) {
    if (conf & PRINTSTACK) != 0 {
        atomic.CompareAndSwapUint32(&config.isPrintStack, 0, 1)
    }
}
测试
func init() {
    errors.SetConfig(errors.PRINTSTACK)
}

func main() {
    a := func() {
        err := errors.Err(nil, "this is an inner error")
        fmt.Print(err.StackTrace())
        b := errors.Errf(err, "this is a %s message", "test").Error()
        fmt.Println(b)
    }
    a()
}

错误信息如下所示
图片描述

结尾

该工具包只是对error信息和堆栈信息的封装,还存在含多不足的地方。如果各位有好的意见。欢迎指点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值