一般的请求响应格式
对于现在大多数系统来说,请求一般就是原始请求参数的JSON格式+HTTP头的Token,响应一般会带上错误码和错误信息,封装为【错误码,错误信息,数据】的JSON格式,请求和响应都会放在HTTP的Body。
对于错误码,常见的选择有数字,字母,和字母+数字这几种方式。
对于HTTP方法,常见的选择有统一POST,获取操作用GET+修改操作用POST,还有RESTful风格的GET、POST、DELETE、PUT等。
对于HTTP状态码,常见的使用方式有统一200,或者使用200、400、401、403、404、500等常见状态码。
对于HTTP头,一般会放置一些权限相关的信息,比如Token。
实现
我们的实现错误码选择字母格式,HTTP方法统一POST,请求参数都放在Body(Token等除外),HTTP状态码使用统一200,使用Gin框架实现。
Service格式
Service是业务逻辑实现的地方,在有异常体系的语言里,我们经常使用:服务名(请求) 响应 throws 异常
这种结构。但是Go一般使用error表示错误,因此Go的服务结构为:服务名(请求) (响应, 错误)
。
比如:登录服务
1 | go复制代码package login |
其中req和rsp都是简单的结构体:
1 | go复制代码package login |
而ErrCodeInvalidParameterUsernameOrPassword是一个ErrCode类型的实例:
1 | go复制代码package login |
这里可以直接返回错误码是因为错误码实现了error接口,下面给出ErrCode的定义。
错误码实现
ErrCode使用了三个字段,错误码、错误信息(给开发者看)和建议(给用户看)。这里ErrCode实现了error接口,因此我们才可以把它当成error类型使用。
1 | go复制代码package common |
这里在最上面定义了一些全局通用的错误码,这样不用每个服务都重复定义这些错误码。
HTTP响应
对于HTTP响应,我们不仅需要带上Service的结果,还需要带上HTTP状态码,错误码,对用户的提示信息。为了简化操作,这里封装了几个工具函数:
1 | go复制代码package common |
Rsp的Msg使用了advice,因为这是给用户看的。
Gin HandlerFunc包装
对于一个服务,在使用Gin框架时,如果我们想把它暴露出去,需要编写一个HandlerFunc函数,如:
1 | go复制代码func LoginHandler(c *gin.Context) { |
但是由于我们的服务、请求、响应、错误码、状态码结构都是统一的,对于不同服务的handler,代码除了在请求参数类型不同外,其余都是一样的,这会导致handler的代码非常的冗余,因此我们利用反射机制对Service进行简单的包装,消除对handler的编写:
1 | go复制代码package wrap |
这样,我们对外暴露服务只需要一行代码:
1 | go复制代码package login |
还可以对wrapper进行扩展, 使其支持进行身份认证,选择是否有返回值(加入一个Config参数),自动注入multipart.Form,header等(使用Go的.(类型)操作对参数类型进行匹配)。
全部代码
Github:github.com/jiaxwu/go_s…
本文转载自: 掘金