Golang中的error

文章目录

      • Golang中的error
        • error源码
        • error创建
        • Unwrap()、Is() 和 As()

参考:https://www.flysnow.org/2019/09/06/go1.13-error-wrapping.html

Golang中的error

error源码

type error interface {Error() string
}

error 是一个接口类型,它包含一个 Error() 方法,返回值为 string。任何实现这个接口的类型都可以作为一个错误使用,Error()这个方法提供了对错误的描述。

error创建

  1. errors.New()
// 源码如下:
package errorsfunc New(text string) error {return &errorString{text}
}// errorString is a trivial implementation of error.
type errorString struct {s string
}func (e *errorString) Error() string {return e.s
}

调用errors.New("xxx")会返回一个errorString的结构体指针,使用fmt.Println(err)时,会自动调用err.Error()方法。

当有些时候我们需要更加具体的信息,即需要具体的“上下文”信息,表明具体的错误值,这就需要用到fmt.Errorf函数。

  1. fmt.Errorf()
// 源码如下:
func Errorf(format string, a ...interface{}) error {p := newPrinter()p.wrapErrs = truep.doPrintf(format, a)s := string(p.buf)var err errorif p.wrappedErr == nil {err = errors.New(s)} else {err = &wrapError{s, p.wrappedErr}}p.free()return err
}

我们可以先看两个例子:

err1 := fmt.Errorf("这个 fmt.Errorf() 创建的错误,错误编码为:%d", 404)
fmt.Printf("err1 错误类型:%T,错误为:%v\n", err1, err1)err2 := fmt.Errorf("err2: %w", err1) // err3包裹err2错误
fmt.Printf("err2 错误类型:%T,错误为:%v\n", err2, err2)

输出:

err1 错误类型:*errors.errorString,错误为:这个 fmt.Errorf() 创建的错误,错误编码为:404err2 错误类型:*fmt.wrapError,错误为:err2: 这个 fmt.Errorf() 创建的错误,错误编码为:404

结合这两个例子,我们再来看源码:首先,代码调用了newPrinter()方法,返回一个pp结构体指针。pp结构体中有两个字段需要关注wrapErrswrappedErr

  • wrapErrs:当格式字符串包含%w动词时,将置为true
  • wrappedErr:记录%w动词的目标;
// newPrinter allocates a new pp struct or grabs a cached one.
func newPrinter() *pp {p := ppFree.Get().(*pp)p.panicking = falsep.erroring = falsep.wrapErrs = falsep.fmt.init(&p.buf)return p
}// pp is used to store a printer's state and is reused with sync.Pool to avoid allocations.
type pp struct {......// wrapErrs is set when the format string may contain a %w verb.wrapErrs bool// wrappedErr records the target of the %w verb.wrappedErr error
}

再看Errorf(),当p.wrappedErr == nil时,errors.New(s)将得到一个errorString的结构体指针(上面提到);

否则,则会返回一个wrapError类型的结构体指针。

func Errorf(format string, a ...interface{}) error {...if p.wrappedErr == nil {err = errors.New(s)} else {err = &wrapError{s, p.wrappedErr}}...
}

wrapError中实现了两个方法:

  • Error():实现了error接口,表示wrapError是一个error类型;
  • Unwrap():返回原错误值,也就是说拆来一层包装;
type wrapError struct {msg stringerr error
}func (e *wrapError) Error() string {return e.msg
}func (e *wrapError) Unwrap() error {return e.err
}

Unwrap()、Is() 和 As()

  1. Unwrap(): 它的功能就是为了获得被嵌套的error。
func Unwrap(err error) error {u, ok := err.(interface {Unwrap() error})if !ok {return nil}return u.Unwrap()
}

调用一次errors.Unwrap函数只能返回最外面的一层error,如果想获取更里面的,需要调用多次errors.Unwrap函数。最终如果一个error不是warpping error,那么返回的是nil

  1. Is()
  • 如果errtarget是同一个,那么返回true;

  • 如果err 是一个wrapError,target也包含在这个嵌套error链中的话,那么也返回true;

  1. As()

我们要把error转为另外一个error,一般都是使用type assertion 或者 type switch,其实也就是类型断言。但是现在给你返回的err可能是已经被嵌套了,甚至好几层了,这种方式就不能用了,所以Golang为我们在errors包里提供了As函数。从功能上来看,As所做的就是遍历err嵌套链,从里面找到类型符合的error,然后把这个error赋予target,这样我们就可以使用转换后的target了,这里有值得赋予,所以target必须是一个指针。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309579.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Java基础]Stream流综合练习

代码如下: package StreamDemoFinal;public class Actor {private String name;public Actor(String name) {this.name name;}public String getName() {return name;}public void setName(String name) {this.name name;} }package StreamDemoFinal;import java.util.Array…

Apple Catching POJ - 2385(基础的动态规划算法)

题意: 给你两个数字n和m;代表会有n个苹果掉落,m次可以移动的机会;有两棵树,开始你站在树1下面,一分钟只能移动一次,下面的数值代表在哪一颗树下会掉落苹果;问你在可移动的范围内&am…

基于 abp vNext 和 .NET Core 开发博客项目 - 用AutoMapper搞定对象映射

上一篇文章集成了定时任务处理框架Hangfire,完成了一个简单的定时任务处理解决方案。本篇紧接着来玩一下AutoMapper,AutoMapper可以很方便的搞定我们对象到对象之间的映射关系处理,同时abp也帮我们是现实了IObjectMapper接口,先根…

磁盘文件系统、挂载

参考:https://zhuanlan.zhihu.com/p/106459445 https://blog.csdn.net/qq_39521554/article/details/79501714 文件系统 持久化的数据是存储在外部磁盘上的,如果没有文件系统,访问这些数据需要直接读写磁盘的sector,而文件系统存…

[Java基础]Stream流的收集操作

代码如下: package CollectPack;import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream;public class CollectDemo {public static void main(String[] args){List<String> list new ArrayList<String>();list.add("林青…

Bound Found POJ - 2566(尺取法+前缀和创造区间变化趋势)

题意&#xff1a; 给定一个数组和一个值t&#xff0c;求一个子区间使得其和的绝对值与t的差值最小&#xff0c;如果存在多个&#xff0c;任意解都可行。 题目&#xff1a; Signals of most probably extra-terrestrial origin have been received and digitalized by The Ae…

MESI 缓存一致性协议

MESI 缓存一致性协议 多核场景下&#xff0c;仅仅依靠CAS这一类硬件原语并不能实现同步&#xff0c;因为原子指令底层实现也可能包含多条微指令&#xff0c;而原子指令的原子性是相对于一个核而言的&#xff0c;多条原子指令在各自的CPU核上都是原子执行的。所以要解决这个问题…

15分钟从零开始搭建支持10w+用户的生产环境(一)

前言这是一个基于中小型企业或团队的架构设计。不考虑大厂。有充分的理由相信&#xff0c;大厂有绝对的实力来搭建一个相当复杂的环境。中小型企业或团队是个什么样子&#xff1f;开发团队人员配置不全&#xff0c;部分人员身兼开发过程上下游的数个职责&#xff1b;没有专职的…

Sum of Consecutive Prime Numbers POJ - 2739(线性欧拉筛+尺取法)

题意&#xff1a; 一些正整数可以由一个或多个连续质数的总和表示。给定一个的正整数n,问满足条件的有多少种情况&#xff1f; 题目&#xff1a; Some positive integers can be represented by a sum of one or more consecutive prime numbers. How many such representat…

高性能IO——Reactor模式

高性能IO——Reactor模式 参考&#xff1a;https://cloud.tencent.com/developer/article/1513447 目前的IO线程处理模型一般可以分为以下三类&#xff1a; 单线程阻塞I/O服务模型&#xff1b; while(true) {socket accept();handle(socket) }多线程阻塞I/O服务模型&#xf…

X-lab 开放实验室开源创新的故事

本报告为“开源软件供应链点亮计划暑期2020活动”中的“大咖说开源”第二期的特邀嘉宾视频&#xff0c;正好借此机会给大家介绍下 X-lab 实验室目前在开源方面开展的一些事情&#xff0c;欢迎大家关注&#xff0c;也欢迎更多热爱开源的朋友们加入&#xff01;摘要&#xff1a;2…

Circle and Points POJ - 1981(单位圆覆盖最多点)

题意&#xff1a; 给你n个点和点的位置&#xff0c;问单位圆最多能覆盖多少个点。 题目&#xff1a; You are given N points in the xy-plane. You have a circle of radius one and move it on the xy-plane, so as to enclose as many of the points as possible. Find h…

Golang 匿名函数、闭包

参考&#xff1a;https://blog.csdn.net/qq_35976351/article/details/81986496 Golang 闭包 匿名函数 Golang支持匿名函数&#xff0c;即在需要使用函数时&#xff0c;再定义函数&#xff0c;匿名函数没有函数名&#xff0c;只有函数体。 匿名函数经常被用于实现回调函数、闭…

ASP.NET Core分布式项目实战(Consent 确认逻辑实现)--学习笔记

任务22&#xff1a;Consent 确认逻辑实现接下来&#xff0c;我们会在上一节的基础上添加两个按钮&#xff0c;同意和不同意&#xff0c;点击之后会把请求 post 到 ConsentController 处理&#xff0c;如果同意会通过 return url 跳转到客户端&#xff0c;如果不同意就会取消&am…

The Last Non-zero Digit POJ - 1150(n!mod p)

题意&#xff1a; 要求你求出n!(n−m)!)\frac{n!}{(n-m)!)}(n−m)!)n!​中最后一个非0的数字. 题目&#xff1a; In this problem you will be given two decimal integer numberN,M. You will have to find the last non-zero digit of the NPM^{N}P_{M}NPM​.This means n…

Istio 1.6——迈向极简主义

从 1.2 版本开始&#xff0c;Istio 进入季度发布的节奏。5 月 21 日发布的 1.6 版本可以说是最准时的一次。我们是否可以理解 Istio 架构简化后的开发工作已经步入了正轨&#xff1f;这次的更新是否会带给我们惊喜&#xff1f;亦或是还有遗憾&#xff1f;让我们一一道来。&…

[Java基础]获取Class类的对象

代码如下: package ClassObjectPack;public class Student {private String name;int age;public String address;public Student(String name, int age, String address) {this.name name;this.age age;this.address address;}public Student() {}private Student(String …

使用PInvoke互操作,让C#和C++愉快的交互优势互补

一&#xff1a;背景1. 讲故事如果你常翻看FCL的源码&#xff0c;你会发现这里面有不少方法借助了C/C的力量让C#更快更强悍,如下所示&#xff1a;[DllImport("QCall", CharSet CharSet.Unicode)][SecurityCritical][SuppressUnmanagedCodeSecurity]private static ex…