错误处理实践
2022-7-27 08:0:0 Author: jiajunhuang.com(查看原文) 阅读量:3 收藏

一个接口,或者一个系统,总是要处理很多异常流程,通常我们都需要以某种形式表达出来,例如返回错误、抛异常。这篇文章我想 讲讲怎么去处理错误。

接口错误

通常对于RESTful接口,我会建议这样返回错误:

{
    "code": 200000,
    "msg": "success",
    "result": {
        "users": []
    }
}

所有的真实payload,都会返回在 result 字段中。为什么要这样设计呢?我们对接的编程语言中,有动态语言,有静态语言。 动态语言处理响应结果非常方便,直接反序列化用就行,对于静态语言,我们往往需要先定义好一个结构体或者类,然后才能 把结果反序列化进对象。所以我们总是有这几个字段,对于定义结构体就会非常方便。

那么为什么 code 是一个比较大的数字呢?大部分场景下,其实我们都不需要使用错误码来指示错误,但是有一些场景我们又需要, 错误码通常是用来指示一个具体的业务错误,我们需要靠查表去看到底是什么错误。另外一个方面,我们其实对HTTP协议中定义的 状态码比较熟悉,比如我们大家都知道200系列是成功,400系列是客户端错误,500系列是服务端错误。因此,我在设计的时候,都会 把错误码,分配在不同的系列里,比如我们想表示用户名不对,首先我们知道,这属于客户端请求错误,因此他要分配在400系列中, 然后在这里找到第一个可用的错误码,例如 400001,依此类推。当然,HTTP状态码会和 code 保持一致,例如当 code 为 400001 时,HTTP状态码返回400。

程序内错误

对于程序内的错误,一般会给我们传递两个信息:1. 属于哪一类错误;2. 具体的错误信息。对于Go语言来说,我一般推荐使用标准库。 我们首先也要对错误进行分类,例如:

  • ErrBadArgument
  • ErrUnauthorized
  • ErrNotFound
  • ErrInternalError

等等,这在Python中很常见,Python自带的异常就在标准库中已经进行过分类,然后业务异常再基于他们开始派生。在Go标准库支持 error继承之后,我们也可以使用类似的方式。

此外,我们还需要将一些错误替换成上述基类错误,例如 gorm.ErrNotFound 替换成 ErrNotFound,然后我们在中间件中进行 统一的处理,将 400 系列的错误信息返回,将 500 系列的错误打印,但是替换掉敏感信息。

不同语言错误处理方式

编程语言都会内置错误处理,这是一门编程语言中非常重要的一部分。

  • 对于C语言来说,最常见的处理方式就是用返回值来指示错误,0表示正常,-1表示出错。有时还会借助errno来表示具体错误。
  • 对于Go语言来说,按照约定,如果想要返回错误,使用返回值中最后一个来返回错误。Go语言中还有 panic/recover 来处理不符合预期的错误。
  • 对于Python来说,我们会使用Exception来表示错误,用 try...except... 来表达。Java、JS与此类似。
  • 对于Haskell,使用 Maybe 来表示错误。Rust 使用类似的方式。

总结

这篇文章中,简单的描述了我个人对于错误处理的一些经验和总结,以及我为什么会这样设计。希望对大家有所帮助。


更多文章
  • 读《管理的实践》
  • frp 源码阅读与分析(二):TCP内网穿透的实现
  • 五天不用微信 - 爽得很
  • frp 源码阅读与分析(一):流程和概念
  • 学习frp源码之简洁的在两个connection之间转发流量
  • 自己动手写一个反向代理
  • 从XMonad迁移到i3
  • 读《债务危机》
  • 服务器IP被ban学到的经验
  • socks5 协议详解
  • 开启HSTS(HTTP Strict Transport Security)
  • 从Chrome切换到Firefox
  • 网络乞讨之合并支付宝和微信的收款二维码
  • nomad简明教程
  • Linux下当笔记本合上盖子之后只使用扩展显示器



  • 文章来源: https://jiajunhuang.com/articles/2022_07_27-how_to_return_error.md.html
    如有侵权请联系:admin#unsafe.sh