go 错误处理设计思考
前段时间准备对线上一个golang系统服务进行内部开源,对代码里面的错误处理进行了一波优化。
优化的几个原因:
- 错误处理信息随意,未分类未定义。看到错误日志不能第一时间定位
- 错误的日志重复,有时候一个错误经过了好几层,每一层都会记录,导致日志混乱
- 错误处理不统一,使用不统一,管理也不统一
优化的解决办法:
- 对错误进行分类,统一定义和使用
- 每一个错误都有冒泡到包的顶层,处理与记日志。使用方只需定义好自己的信息
实施过程
错误分类:函数级,包模块级,系统api级。
函数级别:
还是采用 err != nil 的形式,并且做一个如下的包装。
模块级别
统一返回到对应的goroutine顶层处理
服务对外级别
适当的code和健名的message
底层错误级别
考虑及时panic,暴露有用信息
以下为代码设计:
点击查看代码
package ferrors
import (
"fmt"
"golang.org/x/xerrors"
)
//Errors 新的错误处理方式
type Errors struct {
Code int64
Msg string
}
// Error 输出错误信息
func (e Errors) Error() string {
return fmt.Sprintf("code: %d msg: %s at: %s", e.Code, e.Msg, "错误位置,堆栈信息,可选")
}
// New 创建自定义错误
func New(code int64, str string, arg ...interface{}) *Errors {
if len(arg) > 0 {
str = fmt.Sprintf(str, arg...)
}
return &Errors{Code: code, Msg: str}
}
// newErr 创建通用错误
func newErr(code int64, err error) *Errors {
switch err := err.(type) {
case *Errors:
return err
case nil:
return &Errors{Code: code, Msg: ""}
default:
return &Errors{Code: code, Msg: err.Error()}
}
}
func NewErrNotFound(err error) error {
return newErr(CodeMkNotFound, err)
}
// ErrorEcho example:使用 error wrapping
func ErrorEcho(err error) string {
return fmt.Sprintf("the error %w", err)
}
//ErrorDump example: xerrors 打印堆栈信息
func ErrorDump() {
err := foo1()
fmt.Printf("%v\n", err)
fmt.Printf("%+v\n", err)
}
var myError = xerrors.New("myerror")
func foo() error {
return myError
}
func foo1() error {
return xerrors.Errorf("foo1 : %w", foo())
}
go 错误处理设计思考的更多相关文章
- 用thinkphp进行微信开发的整体设计思考
用thinkphp进行微信开发的整体设计思考 http://www.2cto.com/weixin/201504/388423.html 2015-04-09 0个评论 作者:明 ...
- Atitit. null错误的设计 使用Optional来处理null
Atitit. null错误的设计 使用Optional来处理null 然后,我们再看看null还会引入什么问题. 看看下面这个代码: String address = person.getCount ...
- 2018.8.3 Java中容易犯错误的问题思考与总结
Java容易犯错误的问题思考 float型 float f = 3.4 是否正确 不正确,应该用强制类型转换.如下所示:float f = (float)3.4 或float f = 3.4f 在ja ...
- Java实现本地小数据量缓存尝试与实践&设计思考
话不多说先贴代码 /** * 缓存工具 */ public class ConcurrentHashMapCacheUtils{ /** * 当前缓存个数 */ public static Integ ...
- 深究带PLL的错误复位设计
PLL复位通常犯的错误 或者是像上一篇文章 FPGA知识大梳理(四)FPGA中的复位系统大汇总 中的图一样,也是错误设计.为何呢?看ALTPLL (Phase-Locked Loop) IP Cor ...
- Extjs的架构设计思考,单页面应用 or 多页面?
写在前面:不要认为 EXTJS 高版本就是一个界面改良,在项目中,仍然用 N 张页面,在 N 张页面部署 EXTJS .这种方式不用多讲,效率问题大家都看得出来, EXTJS 是一个集成开发工具,注定 ...
- RESTful API 设计思考
RESTful API 设计思考,内容来源网络加自己的思考 1.RESTful Web API采用面向资源的架构:同一的接口,所以其成员体现为针对同一资源的操作2.SOAP Web API采用RPC风 ...
- 比原链设计思考: 扩展性UTXO模型
用户模型是比原链在最初就需要确定的重要数据结构, 团队的选择还是聚焦在两种典型的模型系统中,Account模型和UTXO模型,和其他大多数区块链设计一样, 选择了模型就决定了协议层的重要实现,两种模型 ...
- 游戏设计思考:对COK的理解和思考
转自:http://www.gameres.com/804983.html 一.前言 发此文的起因是最近加入了一个游戏研究群,受到大家对游戏研究热情的感染,也想将自己对游戏的理解和感悟发出来和大家一起 ...
随机推荐
- 使geoJSONLayer能够加载两种数据类型的geojson数据
问题描述 在使用geoJSONLayer加载geojson数据时,官方文档只支持单一类型的geojson数据加载,当一个geojson数据中出现两种类型的数据时可以尝试一下方法进行解决 本场景为:点击 ...
- C#开发BIMFACE系列43 服务端API之图纸拆分
BIMFACE二次开发系列目录 [已更新最新开发文章,点击查看详细] 在上一篇博客<C#开发BIMFACE系列42 服务端API之图纸对比>的最后留了一个问题,在常规业务场景下,一 ...
- SQL实例_11Oracle基本操作
前言导读 本章介绍了在正常使用Oracle数据库之前进行的常规操作 本章语句的运行需要子啊PLSQL软件中运行 本章导入导出语句需要在虚拟环境中直接运行 1 Oracle创建表空间和用户 --1 创建 ...
- pure-ftpd管理FTP服务器,创建文件夹可以,但上传下载文件不行
两种原因 1.因为pure-ftpd的防火墙端口问题 # Port range for passive connections replies. - for firewalling. PassiveP ...
- dp凸优化/wqs二分学习笔记(洛谷4383 [八省联考2018]林克卡特树lct)
qwq 安利一个凸优化讲的比较好的博客 https://www.cnblogs.com/Gloid/p/9433783.html 但是他的暴力部分略微有点问题 qwq 我还是详细的讲一下这个题+这个知 ...
- c++-string类--insert函数
string &insert(int p0, const char *s);--在p0位置插入字符串s string &insert(int p0, const char *s, in ...
- AOP的简单介绍
1.AOP简介 AOP面向切面编程,采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视.安全检查.缓存) SpringAOP使用纯java实现,不需要专门的编译过程和类加载器,在运行期间以代 ...
- Java并行任务框架Fork/Join
Fork/Join是什么? Fork意思是分叉,Join为合并.Fork/Join是一个将任务分割并行运行,然后将最终结果合并成为大任务的结果的框架,父任务可以分割成若干个子任务,子任务可以继续分割, ...
- 40个Python入门小程序
有不少同学学完Python后仍然很难将其灵活运用.我整理 37 个Python入门的小程序.在实践中应用Python会有事半功倍的效果. 分享 Github 项目,里面收集了 Python 学习资料 ...
- Java继承中父类和子类构造函数的问题
父类有无参构造函数时(显示或隐式),子类的有参和无参构造函数都是默认调用父类的无参构造函数:当父类只有有参构造函数时,子类可以有有参和无参构造函数,子类有参构造函数必须显式调用父类的有参构造函数,子类 ...