Go errors默认加堆栈信息的作用分析

 更新时间:2023年12月08日 08:56:03   作者:煎鱼  
这篇文章主要为大家介绍了Go errors默认加堆栈信息作用分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

背景

在 Go 语言中,错误处理是我们必须涉及和争议比较大的一个功能特性。今天我们不太探讨 if err != nil 的繁杂忧愁。

聚焦在 errors 标准库在排查、定位问题的诉求上。看看大家平时都是怎么做的。

平时我们在返回和处理错误时,一般使用 errors 标准库。其支持以下几个 API:

func As(err error, target any) bool
func Is(err, target error) bool
func Join(errs ...error) error
func New(text string) error
func Unwrap(err error) error

最简单的 Demo 如下:

func main() {
    err := errors.New("煎鱼出现错误了!")
    if err != nil {
        fmt.Println(err)
    }
}

输出结果:

煎鱼出现错误了!

看着非常基础,也没什么特别的。但如果是在生产等正式环境下出问题时,可能就没法这么愉快了。

但比较头疼的是:其错误信息缺乏了调用堆栈,在复杂程序下,你很难直观的知道是具体哪些关联的代码导致出现了这个报错。只能靠在代码中搜错误的文本,去猜测应该是这里的问题。

第三方库解决

因此很多同学会使用第三方的开源库 go-errors/errors。以下是他的简单代码演示:

import (
    "fmt"
    "github.com/go-errors/errors"
)
var Crashed = errors.Errorf("煎鱼变炸鱼了!")
func Crash() error {
    return errors.New(Crashed)
}
func main() {
    err := Crash()
    if err != nil {
        fmt.Println(err.(*errors.Error).ErrorStack())
        return
    }
}

输出结果:

$ go run main.go
*errors.Error 煎鱼变炸鱼了!
/Users/eddycjy/app/go/demo1/main.go:12 (0x1090645)
    main: return errors.New(Crashed)
/Users/eddycjy/app/go/demo1/main.go:12 (0x1090636)
    Crash: return errors.New(Crashed)
/usr/local/Cellar/go/1.21.1/libexec/src/runtime/internal/atomic/types.go:194 (0x103305b)
    (*Uint32).Load: return Load(&u.value)
/usr/local/Cellar/go/1.21.1/libexec/src/runtime/asm_amd64.s:1650 (0x105d501)
    goexit: BYTE    $0x90    // NOP

该库会默认记录 ErrorStack 并且可以通过相应的方法。

新提案

前面提到的问题和解决方案,一直有人在提和重复造新的轮子。最近 Go 核心团队 @Ian Lance Taylor 提出了新的提案《proposal: errors: let GODEBUG=errstacktrace request stack backtraces》希望以此解决这个问题。

在提案中计划:增加一个新的 Go 运行时选项:GODEBUG=errstacktrace

在环境中设置该 GODEBUG 项后,errors.New 和 fmt.Errorf 函数将发生变化,将堆栈跟踪纳入信息中。

新补充的堆栈跟踪将成为 Error 方法返回的字符串的一部分,将会是一个多行的字符串内容。

总结

Go 的 errors 总是纷纷扰扰,本次的提案也是拉扯了多年的结果。本次是想往 GODEBUG 上做开关选项,但也有许多同学想在编译时就能指定,不用每次配一堆 GODEBUG。(虽然实际效果差不多)

整体来讲,这个需求如果能够落地,还是不错的。能够解决一些缺失调用堆栈,不太能明确错误抛出在哪的小麻烦。也能解决一些第三方库存在原因,不用再额外维护了。

以上就是Go errors默认加堆栈信息的作用分析的详细内容,更多关于Go errors堆栈信息的资料请关注脚本之家其它相关文章!

相关文章

  • 一文带你了解Golang中select的实现原理

    一文带你了解Golang中select的实现原理

    select是go提供的一种跟并发相关的语法,非常有用。本文将介绍 Go 语言中的 select 的实现原理,包括 select 的结构和常见问题、编译期间的多种优化以及运行时的执行过程
    2023-02-02
  • Golang 标准库 tips之waitgroup详解

    Golang 标准库 tips之waitgroup详解

    本篇文章给大家介绍Golang 标准库 tips之waitgroup的相关知识,包括使用 channel 实现 WaitGroup 的功能介绍,感兴趣的朋友跟随小编一起看看吧
    2021-07-07
  • go程序部署到linux上运行的实现方法

    go程序部署到linux上运行的实现方法

    本文主要介绍了go程序部署到linux上运行的实现方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • 使用Go语言实现配置文件热加载功能

    使用Go语言实现配置文件热加载功能

    这篇文章主要介绍了使用Go语言实现配置文件热加载功能,以及配置文件热加载包的实现思路,需要的朋友可以参考下
    2018-03-03
  • Golang如何将上传的文件压缩成zip(小案例)

    Golang如何将上传的文件压缩成zip(小案例)

    这篇文章主要介绍了Golang如何将上传的文件压缩成zip(小案例),这是一个简单的golang压缩文件小案例,可做很多的拓展,这里使用的库是archive/zip,在gopkg里面搜zip就行,需要的朋友可以参考下
    2024-01-01
  • Go 数据结构之二叉树详情

    Go 数据结构之二叉树详情

    这篇文章主要介绍了 Go 数据结构之二叉树详情,二叉树是一种数据结构,在每个节点下面最多存在两个其他节点。即一个节点要么连接至一个、两个节点或不连接其他节点,下文基于GO语言展开二叉树结构详情,需要的朋友可以参考一下
    2022-05-05
  • Go语言通过WaitGroup实现控制并发的示例详解

    Go语言通过WaitGroup实现控制并发的示例详解

    Channel能够很好的帮助我们控制并发,但是在开发习惯上与显示的表达不太相同,所以在Go语言中可以利用sync包中的WaitGroup实现并发控制,本文就来和大家详细聊聊WaitGroup如何实现控制并发
    2023-01-01
  • Golang实现Redis网络协议实例探究

    Golang实现Redis网络协议实例探究

    这篇文章主要为大家介绍了Golang实现Redis网络协议实例探究,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • Golang如何调用Python代码详解

    Golang如何调用Python代码详解

    这篇文章主要给大家介绍了关于Golang如何调用Python代码的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-10-10
  • golang通过递归遍历生成树状结构的操作

    golang通过递归遍历生成树状结构的操作

    这篇文章主要介绍了golang通过递归遍历生成树状结构的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04

最新评论