Go语言错误处理最佳实践

news2024/11/17 18:29:10

错误处理实践

我们在go语言中设计error的处理体系时候, 一般都会去做下面两点

直接使用errors.New()生成error接口的值
扩展error接口, 并定义扩展error接口的实现类型

error接口是什么?

go语言的error是一个接口类型, 其源码如下:

type error interface {
	Error() string
}

我们可以定义它的实现类型, 比如我们经常使用到的errors.New()方法, 返回值为一个error接口的实现类型*errorString的结构体字面量

package errors

func New(text string) error {
	return &errorString{text}
}

type errorString struct {
	s string
}

func (e *errorString) Error() string {
	return e.s
}

//package main
xxxerr := errors.New("xxx")

所以我们可以直接调用errors.New()为我们生成一个error接口的值

扩展的error接口

我们为什么需要对error接口进行扩展呢?, 原因是error的实现类型范围太大了, 细粒度不够小, 所以我们需要实现更加精细的控制, 关于这种设计我们可以参考go语言标准库中的一些error处理代码, 比如下面的

type Error interface {
	//嵌入了error接口, 实现net.Error也会实现error
    error

    //扩展
    Timeout() bool
    Temporary() bool
}

然后我们又可以定义一个类型来实现这个扩展错误接口类型, 比如下面这个OpError:

type OpError struct {
	Op string
	Net string
	Source Addr
	Addr Addr
	Err error
}

//实现函数1
func (e *OpError) Error() string {
	return ""
}

//下面是实现函数2
func (e *OpError) Timeout() bool {
	//对应的处理逻辑
    return true
}

//下面是实现函数2
func (e *OpError) Temporary() bool {}

我们发现该结构体中存在一个名字叫做Err的类型为error的字段, 它代表了该错误的潜在错误, 有可能OpError类型的错误值还包含了AddrError这种错误
通过这种类型建立起树形的错误体系, 用统一字段建立可追溯的链式错误关联, 我们就可以建立起来一套优秀的错误处理机制
为了更好的表示, 我画了一张图

在这里插入图片描述

具体的错误

因为Go语言的error是一个接口, 所以这个它的值的实际类型是非常复杂的, 于是我们就需要去判断它的值的一个实际类型

如果错误值在某一个范围内, 我们可以使用类型断言表达式或者类型断言+switch语句进行判断
对于已有相应变量且类型相同的一系列错误值, 一般直接使用判等操作 + switch语句
没有相应变量且类型未知的一系列错误值, 只能使用其错误信息的字符串表示形式来判断

下面我们分别来看上面的内容: 首先是第一点, 已知错误值的范围比如: {os.PathError|os.LinkError|os.SyscallError|exec.Error}, 是它们中的一个, 我们可以直接使用类型断言+switch, 然后返回潜在错误类型

func underlyingError(err error) error {
  switch err := err.(type) {
  case *os.PathError:
    return err.Err
  case *os.LinkError:
    return err.Err
  case *os.SyscallError:
    return err.Err
  case *exec.Error:
    return err.Err
  }
  return err
}

当我已经知道某个错误是哪一个, 我们直接使用判等操作+switch,

printError := func(i int, err error) {
    if err == nil {
        fmt.println("nil error")
        return
    }

    err = underlyingError(err)

    switch err {  
    case os.ErrClosed:    
        fmt.Printf("error(closed)[%d]: %s\n", i, err)  
    case os.ErrInvalid:    
        fmt.Printf("error(invalid)[%d]: %s\n", i, err)  
    case os.ErrPermission:    
        fmt.Printf("error(permission)[%d]: %s\n", i, err)  
    }
}

通过上面这种直接判等操作, 我们就可以锁定具体的错误值了

对于上面两种情况, 我们都会有比较明确的方法去解决, 但是我们对一个错误值可能代表的含义知道的很少, 那么就只能通过错误信息去判断了

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

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

相关文章

Springboot 接收POST、json、文本数据实践

一、接收 Form 表单数据 1,基本的接收方法 (1)下面样例 Controller 接收 form-data 格式的 POST 数据: import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.Request…

Python各文件类型对比: .py、.ipynb、.pyi、.pyc、.pyd

在Python中,各文件类型的作用如下: .py文件:是Python代码文件的标准扩展名,其中包含可执行的Python代码。 .ipynb文件:是Jupyter Notebook的文件扩展名,其中包含交互式代码、文本、图像、公式等多种元素&am…

React笔记:useState

1 介绍 useState 是 React 中一个非常重要的钩子(Hook),允许在函数组件中添加状态。 2 基本用法 useState 是一个函数,它接收一个参数(初始状态值)并返回一个数组。 返回的这个数组包含两个元素&#xf…

大数据之LibrA数据库系统介绍

简介 LibrA是一个基于开源数据库Postgres-XC开发的分布式并行关系型数据库系统。 LibrA提供了以下功能: 标准SQL支持 支持标准的SQL92/SQL2003规范,支持GBK和UTF-8字符集,支持SQL标准函数与OLAP分析函数,支持存储过程。 数据库…

JAVA代码实现十大经典排序算法

JAVA代码实现十大经典排序算法 0、排序算法说明 0.1 排序的定义 对一序列对象根据某个关键字进行排序。 0.2 术语说明 稳定:如果a原本在b前面,而ab,排序之后a仍然在b的前面;不稳定:如果a原本在b的前面&#xff0c…

游戏缺少dll文件用什么修复?教你多种dll文件修复方法搞定!

在玩游戏的时候,有时候会遇到一些dll文件缺失的问题,导致游戏无法正常运行。这对于广大游戏爱好者来说无疑是一种巨大的打击。但是不要担心,我们总会有方法来解决这个问题。本文将详细介绍几种解决方法,帮助你轻松修复游戏缺少dll…

C++医院影像科PACS源码:三维重建、检查预约、胶片打印、图像处理、测量分析等

PACS连接DICOM接口的医疗器械(如CT、MRI、CR、DR、DSA、各种窥镜成像系统设备等),实现图像无损传输,实现DICOM胶片打印机回传打印功能,支持各种图像处理,可以进行窗技术调节,与登记台管理系统共…

RabbitMQ开启消息发送确认和消费手动确认

开启RabbitMQ的生产者发送消息到RabbitMQ服务端的接收确认(ACK)和消费者通过手动确认或者丢弃消费的消息。 通过配置 publisher-confirm-type: correlated 和publisher-returns: true开启生产者确认消息。 server:port: 8014spring:rabbitmq:username: …

举个栗子~Tableau 技巧(258):使用参数高亮文本表中的行

经常有数据粉咨询:如何高亮文本表中的某一行,像 Excel 那样给数据行增加底色,达到突出显示的效果。 其实,可以通过参数来实现这个需求。如下示例,在参数中键入不同的行数,视图就高亮对应的数据行。 那么&…

idea部署Tomcat web项目报错

idea部署Tomcat web项目报错 facets,a. 新增web, b. 指定好web路径, c. 右下脚创建 Artifacts 必须添加src/webapp/WEB-INF/lib, jar包到SDKs中 新建lib包文件夹,添加依赖jar包进来

【Python 零基础入门 】安装 环境配置

【Python 零基础入门 】第一课 安装 & 环境配置 Python 零基础入门 第一课 安装 & 环境配置Python 的历史Python 的前景安装了解你的操作系统Python 安装环境配置 PyCharm 安装第一个程序 Python 零基础入门 第一课 安装 & 环境配置 在当今的技术时代, 编程语言正…

QECon大会亮相产品,更合适的企业级测试平台:RunnerGo

在当今这个数字化时代,应用程序的性能至关重要。一款可靠的性能测试工具,能够为企业带来无数的好处。最近,一款名为RunnerGo的开源性能测试工具备受瞩目。本文将详细介绍RunnerGo的特点、优势以及如何解决性能测试中的痛点。 RunnerGo产品介绍…

用go获取IPv4地址,WLAN的IPv4地址,本机公网IP地址,本机空闲端口详解

文章目录 获取IPv4地址获取WLAN的IPv4地址获取本机公网IP地址获取本机空闲端口 获取IPv4地址 下面的代码会打印出本机所有的IPv4地址。这个方法可能会返回多个IP地址,因为一台机器可能有多个网络接口,每个接口可能有一个或多个IP地址。 package mainim…

Graph RAG: 知识图谱结合 LLM 的检索增强

本文为大家揭示 NebulaGraph 率先提出的 Graph RAG 方法,这种结合知识图谱、图数据库作为大模型结合私有知识系统的最新技术栈,是 LLM 系列的第三篇,加上之前的图上下文学习、Text2Cypher 这两篇文章,目前 NebulaGraph LLM 相关的…

接口测试——接口协议抓包分析与mock_L3

目录: 弱网测试mock的价值与意义mock实战练习 Rewrite 原理Map Local 原理Map Remote 原理使用curl发送请求tcpdump与wireshark的使用 1.弱网测试 什么是弱网测试? 按照移动的特性,一般应用低于 3G、弱信号的 Wifi 可以划分为弱网弱网测试…

im即时通讯系统源码/如何搭建一个自己的im即时通讯呢?

​一,思路梳理 1,首先思考群聊的实现方式。 每当一个用户使用websocket建立连接时,都会存放一个连接对象(在connectMap集合存放,键为sessionId,值为该连接对象),每次当用户发送一条…

js Learn(异步JavaScript)

在这个模块中,我们来看看异步JavaScript,为什么它很重要,以及如何使用它来有效地处理潜在的阻塞操作,比如从服务器获取资源。 指南 异步JavaScript介绍 在本文中,我们将学习同步(synchronous&#xff09…

TLR4-IN-C34-C2-COO,一种结合了TLR4抑制剂TLR4-IN-C34的连接器

TLR4-IN-C34-C2-COO是一种结合了TLR4抑制剂TLR4-IN-C34的连接器,在免疫调节中发挥重要作用,它通过抑制TLR4信号通路的传导,从而达到降低炎症反应的目的。TLR4是Toll样受体家族中的一员,它主要识别来自细菌和病毒的保守模式&#x…

零碳联盟:改变世界,实现绿色能源的共同梦想

如今,全球气候变暖已然成为我们面对的头等大事。温室气体的排放不断升高,导致地球温度上升,带来了严重的极端气候、冰川消融和海平面上升等问题。这一切都源于人类活动,特别是大规模使用化石燃料,如煤炭发电、供暖以及…

AIGC | LLM 提示工程 -- 如何向ChatGPT提问

当前生成式人工智能已经成为革命性的驱动源,正在迅速地重塑世界,将会改变我们生活方式和思考模式。LLM像一个学会了全部人类知识的通才,但这不意味每个人可以轻松驾驭这个通才。我们只有通过学习面向LLM的提示工程,才可以更好的让…