Go error的使用方式详解

目录
  • 概述
    • error使用方式
      • 1.直接判等
      • 2.组合error接口,构建更强大的error接口
      • 3.Errno模式
      • 4.Go1.13的Wrap模式
      • 5. Go版本低时的链式error

概述

当我们需要在Go项目中设计error,就不得不先知道Go error几种常用方法。标准库是一个非常好的学习方式,除此之外Go1.13的errors特性也需要掌握。

error使用方式

1.直接判等

这里的判等又分为变量判等和类型判等。
适用于pkg中预先定义好了多个error变量或类型,err只可能是这些变量的其中一个。
案例:os.IsExist(err)

// 变量判等
var errObj = errors.New(errObj)
func IsErrObj(err error) bool {
    return err == errObj
}
// 类型判等
type PathError struct {
   Op   string
   Path string
   Err  error
}
func IsPathError(err error) bool {
    switch e := err.(type) {
    case *PathError:
        return true
    default:
        return false
    }
} 

2.组合error接口,构建更强大的error接口

适用于构造pkg级别专用的error接口类型,同时在struct中组合Err变量表示底层错误
案例:net.Error interface

package net
type Error interface {
   error
   Timeout() bool   // Is the error a timeout?
   Temporary() bool // Is the error temporary?
}

type AddrError struct {
   Err  string
   Addr string
}

3.Errno模式

我们知道Linux有大量的错误码,表示了各种错误类型,对于很多系统而言错误码非常好用。Go如何兼容这种errono模式呢?
案例:sysacall.Errno

type Errno uintptr
func (e Errno) Error() string {
   if 0 <= int(e) && int(e) < len(errors) {
      s := errors[e]
      if s != "" {
         return s
      }
   }
   return "errno " + itoa.Itoa(int(e))
}

4.Go1.13的Wrap模式

在一些场景下,error是有链式关系的,我们固然可以自己实现一种链式error类型,但是Go1.13引入了语言级别的支持。它非常简单,只要3个重要的用法:

// 创建error
err2 := fmt.Errorf("%w", err1)
// 判断error链条中是否包含某个err变量
ok := errors.Is(err2, err1) // true
// 判断error链条中是否可赋值为某个err类型,成功则赋值给target
type Errno int
func (e *Errno) Error() string {
   return strconv.Itoa(int(*e))
}

func test() {
    var no = Errno(1)
    no1 := fmt.Errorf("%w", &no)
    no2 := fmt.Errorf("%w", no1)

    var target *Errno
    ok := errors.As(no2, target)
    fmt.Println(ok, target) // true, 1
}

以上代码都依赖 errors.Unwrap 函数,这个函数通过反射解析出链式error的上一个error。
从代码可以看出,error.Is 用于我们有2个err变量的情况下,判断前者是否链接了后者;
error.As 用于我们有一个err变量和一种error类型,想要判断链子中是否包含了这种error类型,如果是,我们顺带将值保存在target中,相当于丢弃了一些链式的信息,返璞归真。 这里有2个注意点:

  • Unwrap依赖反射,我们知道Go的反射是很慢的,所以需要考虑性能的场景慎用
  • As函数使用是,target本身必须是struct的指针类型,并且要取地址,否则可能会panic

5. Go版本低时的链式error

有时候我们会看到 github.com/pkg/errors 这个包,它其实就是老版本Go想要使用链式error所引用的包,它常用的方法是 Wrap 和 Cause,所以看到这2个函数就可以猜到一个项目没有使用新的errors特性。

到此这篇关于Go error的使用方式选择的文章就介绍到这了,更多相关Go error使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅析golang开发Error的使用详解

    Error是Go语言开发中最基础也是最重要的部分,跟其他语言的try catch的作用基本一致,想想在PHP JAVA开发中,try catch 不会使用,或者使用不灵活,就无法感知到程序运行中出现了什么错误,是特别可怕的一件事. Error 基础 Golang中 error类型就是一个最基本interface,定义了一个Error()的方法 type error interface { Error() string } 平常使用最多的是这样的 errors.New("error")

  • Go Error 嵌套实现创建方式

    目录 创建 Error errors.New() fmt.Errorf() Wrap Error 后记 Go Error 的设计哲学是 「Errors Are Values」. 这句话应该怎么理解呢?翻译起来挺难的.不过从源码的角度来看,好像更容易理解其背后的含义. Go Error 源码很简单,寥寥几行: // src/builtin/builtin.go type error interface { Error() string } error 是一个接口类型,只需要实现 Error() 方

  • Go error的使用方式详解

    目录 概述 error使用方式 1.直接判等 2.组合error接口,构建更强大的error接口 3.Errno模式 4.Go1.13的Wrap模式 5. Go版本低时的链式error 概述 当我们需要在Go项目中设计error,就不得不先知道Go error几种常用方法.标准库是一个非常好的学习方式,除此之外Go1.13的errors特性也需要掌握. error使用方式 1.直接判等 这里的判等又分为变量判等和类型判等.适用于pkg中预先定义好了多个error变量或类型,err只可能是这些变量

  • IOS 指纹识别两种方式详解及实例

    IOS 指纹识别两种方式详解及实例 首先引入类名: #import <LocalAuthentication/LocalAuthentication.h> 然后在实现指纹识别的地方放入如下代码: 方式一: LAContext *lacontext = [[LAContext alloc]init]; // 判断设备是否支持指纹识别 BOOL isSupport = [lacontext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWit

  • Android Webview上的ssl warning的处理方式详解及实例

    Android Webview上的ssl warning的处理方式详解 前言: 因为最近遇到google pay上汇报的安全漏洞问题,需要处理ssl warning. 安全提醒 您的应用中 WebViewClient.onReceivedSslError 处理程序的实施方式很不安全.具体来说,这种实施方式会忽略所有 SSL 证书验证错误,从而使您的应用容易受到中间人攻击.攻击者可能会更改受影响的 WebView 内容.读取传输的数据(例如登录凭据),以及执行应用中使用 JavaScript 的代

  • PHP定义字符串的四种方式详解

    1.简介 在PHP中这门语言中,因为是弱类型语言,因此使用变量时不需提前定义即可使用. 我们在使用php进行开发的时候,大多数使用双引号.单引号进行定义字符串.既然有这两种方式,那么他们之间肯定是有区别的. 并且,除了单双引号定义字符串这两种方式外,php还增加了heredoc和nowdoc这两种语法糖进行补充. 2.单引号与双引号 2.1.单引号 在单引号中,任何特殊字符都会按原样输出[除\\.\'将会被转义输出] eg. <?php $var = 'this is a var!'; echo

  • angularjs $http调用接口的方式详解

    如下所示: $http.get("/merchantmall/merchant.json") .success(function(data, status, headers, config) { console.log(arguments); }) .error(function(data, status, headers, config) { console.log(arguments); }) $http({url: "/merchantmall/merchant.jso

  • vue项目中企业微信使用js-sdk时config和agentConfig配置方式详解

    1.如果只使用config配置的相关js接口 可采用如下方式引入 执行 npm weixin-sdk-js --save 局部引入 在vue页面中 import wx from 'weixin-sdk-js'; 全局引入 在vue 的main.js 页面中 引入后编写到vue原型链上,然后全局调用 import wx from "weixin-sdk-js"; Vue.prototype.$wx = wx; 2.如果要使用agentConfig配置的相关接口 一定不要执行npm命令引入

  • JS实现深拷贝和浅拷贝的方式详解

    目录 一. 基本类型数据拷贝 二. 引用类型数据拷贝 1.浅拷贝 2.深拷贝 说道数据拷贝就离不开数据类型,在JS中数据类型分为基本类型和引用类型 基本类型: number, boolean,string,symbol,bigint,undefined,null 引用类型: object 以及一些标准内置对象 Array.RegExp.String.Map.Set.. 一. 基本类型数据拷贝 基本类型数据都是值类型,存储在栈内存中,每次赋值都是一次复制的过程 var a = 12; var b

  • Python绘制散点密度图的三种方式详解

    目录 方式一 方式二 方式三 方式一 import matplotlib.pyplot as plt import numpy as np from scipy.stats import gaussian_kde from mpl_toolkits.axes_grid1 import make_axes_locatable from matplotlib import rcParams config = {"font.family":'Times New Roman',"fo

  • Spring中Bean的三种实例化方式详解

    目录 一.环境准备 二.构造方法实例化 三.分析Spring的错误信息 四.静态工厂实例化 4.1 工厂方式创建bean 4.2 静态工厂实例化 五.实例工厂与FactoryBean 5.1 环境准备 5.2 实例工厂实例化 5.3 FactoryBean的使用 六.bean实例化小结 一.环境准备 准备开发环境 创建一个Maven项目 pom.xml添加依赖 resources下添加spring的配置文件applicationContext.xml 最终项目的结构如下: 二.构造方法实例化 在

  • MyBatis源码剖析之Mapper代理方式详解

    目录 源码剖析-getmapper() 源码剖析-invoke() 具体代码如下: //前三步都相同 InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSess

随机推荐