全国旗舰校区

不同学习城市 同样授课品质

北京

深圳

上海

广州

郑州

大连

武汉

成都

西安

杭州

青岛

重庆

长沙

哈尔滨

南京

太原

沈阳

合肥

贵阳

济南

下一个校区
就在你家门口
+
当前位置:首页  >  技术干货

一行代码实现一个RESTful接口

发布时间:2022-09-23 11:24:00
发布人:syq

  背景

  基于现在微服务或者服务化的思想,我们大部分的业务逻辑处理函数都是长这样的:

  比如grpc服务端:

1

  grpc客户端:

2

  有些服务我们需要把它包装为RESTful形式的接口,一般需要经历以下步骤:

  指定HTTP方法、URL

  鉴权

  参数绑定

  处理请求

  处理响应

  可以发现,参数绑定、处理响应几乎都是一样模板代码,鉴权也基本上是模板代码(当然有些鉴权可能比较复杂)。

  而Ginrest库就是为了消除这些模板代码,它不是一个复杂的框架,只是一个简单的库,辅助处理这些重复的事情,为了实现这个能力使用了Go1.18的泛型。

  特性

  这个库提供以下特性:

  封装RESTful请求响应

  封装RESTful请求为标准格式服务

  封装标准格式服务处理结果为标准RESTful响应格式:Rsp{code, msg, data}

  默认使用统一数字错误码格式:[0, 4XXXX, 5XXXX]

  默认使用标准错误格式:Error{code, msg}

  默认统一状态码[200, 400, 500]

  提供Recovery中间件,统一panic时的响应格式

  提供SetKey()、GetKey()方法,用于存储请求上下文(泛型)

  提供ReqFunc(),用于设置Req(泛型)

  使用例子

  首先我们实现两个简单的服务:

3

  然后使用Gin+Ginrest包装为RESTful接口:

  可以看到Register()里面每个接口都只需要一行代码!

4

  运行上面代码,然后尝试访问接口,可以看到返回结果:

5

  实现原理

  Do()和DoOpt()都会转发到do(),它其实是一个模板函数,把脏活累活给处理了:

6

  功能列表

  处理请求

  用于把一个标准服务封装为一个RESTfulgin.HandlerFunc,对应Do()、DoOpt()函数。

  DoOpt()相比于Do()多了一个opts参数,因为很多rpc框架客户端都有一个opts参数作为结尾。

  还有一个BindJSON(),用于把请求体包装为一个Req结构体:

7

  如果无法使用Do()和DoOpt()则可以使用此方法。

  处理响应

  用于把rsp、error、errcode、errmsg等数据封装为一个JSON格式响应体,对应ProcessRsp()、Success()、Failure()、FailureCodeMsg()函数。

  比如ProcessRsp()需要带上rsp和error,这样业务里面就不需要再写如下模板代码了:

8

  响应格式统一为:

9

  Success()用于处理成功情况:

10

  其余同理。

  如果无法使用Do()和DoOpt()则可以使用这些方法。

  处理错误

  一般我们都需要在出错时带上一个业务错误码,方便客户端处理。因此我们需要提供一个合适的error类型:

11

  我们提供了一些函数方便使用Error,对应NewError()、ToError()、ErrCode()、ErrMsg()、ErrEqual()函数。

  比如NewError()生成一个Error类型error:

12

  请求上下文操作

  Gin的请求是链式处理的,也就是多个handler顺序的处理一个请求,比如:

13

  这个接口经历了Verify和ginrest.Do两个handler,其中我们在Verify的时候通过认证知道了用户的身份信息(比如uid),我们希望把这个uid存起来,这样可以在业务逻辑里使用。

  因此我们提供了SetKey()、GetKey()两个函数,用于存储请求上下文:

  比如认证通过后我们可以设置UID到上下文,然后在reqFunc()里读取设置到req里面(下面介绍)。

14

  请求结构体处理

  上面我们设置了请求上下文,比如UID,但是其实我们并不知道具体这个UID是需要设置到req里的哪个字段,因此我们提供了一个回调函数ReqFunc(),用于设置Req:

15

  

  如果这个库的设计不符合具体的业务,也可以按照这种思路去封装一个类似的库,只要尽可能的统一请求、响应的格式,就可以减少很多重复的模板代码。

相关文章

机器学习中Inference和predict的区别是什么?

机器学习中Inference和predict的区别是什么?

2023-10-15
kd-tree和ball-tree在算法实现原理上有什么区别?

kd-tree和ball-tree在算法实现原理上有什么区别?

2023-10-15
nn.Linear()和nn.Embedding()有什么区别?

nn.Linear()和nn.Embedding()有什么区别?

2023-10-14
敏捷开发和迭代式开发的根本区别是什么?

敏捷开发和迭代式开发的根本区别是什么?

2023-10-14

最新文章

常见网络安全面试题:Windows常用的命令有哪些?

常见网络安全面试题:Windows常用的命令有哪些?

2023-10-09
常见网络安全面试题:根据设备告警如何展开排查?

常见网络安全面试题:根据设备告警如何展开排查?

2023-10-09
常见网络安全面试题:mysql加固呢?(数据库加固)

常见网络安全面试题:mysql加固呢?(数据库加固)

2023-10-09
常见网络安全面试题:windows和linux加固?(操作系统加固)

常见网络安全面试题:windows和linux加固?(操作系统加固)

2023-10-09
在线咨询 免费试学 教程领取