基于golang如何实现error工具包详解

 更新时间:2018年09月03日 17:12:11   作者:zcv8  
Go 语言使用 error 类型来返回函数执行过程中遇到的错误,下面这篇文章主要给大家介绍了关于如何基于golang实现error工具包的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

前言

对于一门编程语言的开发者,类库包管理是一项考核编程语言成熟度的重要指标之一,Golang 也不例外。笔者在日常使用Golang语言开发系统程序时发现,在 Golang 的世界里,存在着大量的技术实现讨论和各种自制的解决方案。

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

设计思想

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

实现思路

工具包中主要是对堆栈信息的处理,就是如何才能定位到error的产生位置,通过查看官方文档,我们发现通过runtime包中的Callers和CallersFrames函数可以获取当前函数调用的堆栈信息。并且通过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信息和堆栈信息的封装,还存在含多不足的地方。如果各位有好的意见。欢迎指点。

总结:

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • Go语言基础go install命令使用示例详解

    Go语言基础go install命令使用示例详解

    这篇文章主要为大家介绍了Go语言基础go install命令的使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2021-11-11
  • go语言题解LeetCode1299将每个元素替换为右侧最大元素

    go语言题解LeetCode1299将每个元素替换为右侧最大元素

    这篇文章主要为大家介绍了go语言LeetCode刷题1299将每个元素替换为右侧最大元素示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Go编译32位GNU静态链接库的方法

    Go编译32位GNU静态链接库的方法

    Go链接库系统的难用可谓是人尽皆知,不同Go版本编译出来的不兼容,而且只支持GNU的,不能编译出Windows上的dll和lib。这篇文章给大家介绍Go编译32位GNU静态链接库的方法,感兴趣的朋友一起看看吧
    2020-05-05
  • Golang filepath包常用函数详解

    Golang filepath包常用函数详解

    本文介绍与文件路径相关包,该工具包位于path/filepath中,该包试图与目标操作系统定义的文件路径兼容。本文介绍一些常用函数,如获取文件绝对路径,获取文件名或目录名、遍历文件、分割文件路径、文件名模式匹配等函数,并给具体示例进行说明
    2023-02-02
  • 详解go-zero如何实现令牌桶限流

    详解go-zero如何实现令牌桶限流

    令牌桶算法既能够将所有的请求平均分布到时间区间内,又能接受服务器能够承受范围内的突发请求,因此是目前使用较为广泛的一种限流算法,本文就来看看go-zero如何实现令牌桶限流的吧
    2023-08-08
  • golang判断chan channel是否关闭的方法

    golang判断chan channel是否关闭的方法

    这篇文章主要介绍了golang判断chan channel是否关闭的方法,结合实例形式对比分析了Go语言判断chan没有关闭的后果及关闭的方法,需要的朋友可以参考下
    2016-07-07
  • golang操作elasticsearch的实现

    golang操作elasticsearch的实现

    这篇文章主要介绍了golang操作elasticsearch,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • 基于Golang开发一个轻量级登录库/框架

    基于Golang开发一个轻量级登录库/框架

    几乎每个项目都会有登录,退出等用户功能,而登录又不单仅仅是登录,我们要考虑很多东西。所以本文就来用Golang开发一个轻量级登录库/框架吧
    2023-05-05
  • golang内存逃逸的学习笔记

    golang内存逃逸的学习笔记

    内存逃逸是 Go 语言编程中一个特别需要注意的问题,会影响到程序的性能和稳定性,本文主要介绍了golang内存逃逸的学习笔记,感兴趣的可以了解一下
    2024-05-05
  • golang grpc 负载均衡的方法

    golang grpc 负载均衡的方法

    这篇文章主要介绍了golang grpc 负载均衡的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07

最新评论