自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Go API 多種響應(yīng)的規(guī)范化處理和簡(jiǎn)化策略

開(kāi)發(fā) 前端
既然一個(gè)項(xiàng)目接口的響應(yīng)格式是確定的,那么在搭建項(xiàng)目的時(shí)候就需要我們提前封裝一個(gè)通用的接口響應(yīng)組件,讓實(shí)現(xiàn)業(yè)務(wù)邏輯的代碼能盡量傻瓜式地調(diào)用響應(yīng)組件,由響應(yīng)組件負(fù)責(zé)生成響應(yīng)返回給客戶端。

一個(gè)對(duì)外提供API接口的服務(wù),在真正動(dòng)工開(kāi)發(fā)接口前一般需要先確定一下接口響應(yīng)的通用格式,無(wú)論接口響應(yīng)里返不返回業(yè)務(wù)數(shù)據(jù),返回的數(shù)據(jù)是字符串、列表、對(duì)象還是其他類型都會(huì)遵照這個(gè)通用的響應(yīng)格式。

既然一個(gè)項(xiàng)目接口的響應(yīng)格式是確定的,那么在搭建項(xiàng)目的時(shí)候就需要我們提前封裝一個(gè)通用的接口響應(yīng)組件,讓實(shí)現(xiàn)業(yè)務(wù)邏輯的代碼能盡量傻瓜式地調(diào)用響應(yīng)組件,由響應(yīng)組件負(fù)責(zé)生成響應(yīng)返回給客戶端。

這篇內(nèi)容我跟大家一起分析項(xiàng)目接口響應(yīng)的通用格式應(yīng)該是什么樣的,然后動(dòng)手為Go項(xiàng)目封裝一個(gè)統(tǒng)一的接口響應(yīng)組件,讓它能為項(xiàng)目生成通用格式的響應(yīng),該組件還會(huì)對(duì)返回分頁(yè)數(shù)據(jù)的接口做一個(gè)邏輯簡(jiǎn)化,為錯(cuò)誤響應(yīng)做好兜底。大家跟著我一起來(lái)看看吧。

圖片圖片

本節(jié)對(duì)應(yīng)的代碼版本為c5,訂閱后加入課程的GitHub項(xiàng)目后可以直接查看本章節(jié)對(duì)應(yīng)的代碼更新

圖片圖片

確定項(xiàng)目接口響應(yīng)的通用格式

一般的響應(yīng)格式必須有這么幾個(gè)要素:

  • code : 響應(yīng)中的業(yè)務(wù)Code碼,一般0表示成功,其他碼值會(huì)對(duì)應(yīng)到不同的錯(cuò)誤上,在《Go項(xiàng)目Error的統(tǒng)一規(guī)劃管理策略》中已經(jīng)教大家怎么按模塊管理Error了,響應(yīng)組件會(huì)直接使用那些預(yù)定義Error上的code碼值作為響應(yīng)code。
  • msg: 這個(gè)好理解就是個(gè)信息字符串,有可能前端會(huì)以這個(gè)值作為客戶端的toast 消息。
  • data: 接口中返回的數(shù)據(jù),可能是對(duì)象也可能是列表,這個(gè)就需要負(fù)責(zé)各個(gè)接口的前端組件去對(duì)應(yīng)解析啦
  • request_id: 有的團(tuán)隊(duì)會(huì)要求返回這個(gè)request_id ,不是必須的,但是有它,需要查數(shù)據(jù)的時(shí)候會(huì)更好的從日志里回溯請(qǐng)求在服務(wù)端都發(fā)生了什么。
  • pagination: 接口返回列表數(shù)據(jù),有可能需要返回總行數(shù)之類的信息,好去請(qǐng)求下一頁(yè)數(shù)據(jù),一般在管理后臺(tái)類的項(xiàng)目中使用較多, 移動(dòng)端可能會(huì)更喜歡拿數(shù)據(jù)的last id 去請(qǐng)求下一批數(shù)據(jù)。

確定好接口響應(yīng)的通用格式后,接下來(lái)我們開(kāi)始為項(xiàng)目封裝響應(yīng)組件。

封裝響應(yīng)組件

我們先在 common 目錄下新建 app 目錄,其中新增兩個(gè)文件 response.go 和 pagination.go

.
|-- common
|   |-- app
|       |---pagination.go
|       |---response.go
|......
|-- main.go
|-- go.mod
|-- go.sum

在 response.go 定義項(xiàng)目接口的統(tǒng)一響應(yīng)結(jié)構(gòu)

type response struct {
 ctx        *gin.Context
 Code       int         `json:"code"`
 Msg        string      `json:"msg"`
 RequestId  string      `json:"request_id"`
 Data       interface{} `json:"data,omitempty"`
 Pagination *Pagination `json:"pagination,omitempty"`
}

response 中的 Pagination 是分頁(yè)信息,其結(jié)構(gòu)定義在pagination.go文件中。

type Pagination struct {
    Page      int `json:"page"`
    PageSize  int `json:"page_size"`
    TotalRows int `json:"total_rows"`
}

reponse定義中 Data 和 Pagination 的結(jié)構(gòu)體 tag 中 都有一個(gè) json:"xxx,omitempty"這個(gè) omitempty 的意思是進(jìn)行JSON格式化的時(shí)候忽略空值。

比如我們的API返回單一的對(duì)象或者不需要分頁(yè)的列表信息時(shí)不會(huì)設(shè)置響應(yīng)的分頁(yè)信息,加上這個(gè)標(biāo)簽后接口的響應(yīng)結(jié)果中就不會(huì)有pagination這個(gè)字段了。data字段也是同一個(gè)道理。

所以我們分別給response定義了 SuccessOk和Success方法,前一個(gè)情況接口程序直接調(diào)用SuccessOk即返回不帶數(shù)據(jù)的成功響應(yīng),后者返回帶數(shù)據(jù)的接口響應(yīng)

我們來(lái)看一下 response 中提供的方法。

// SetPagination 設(shè)置Response的分頁(yè)信息
func (r *response) SetPagination(pagination *Pagination) *response {
 r.Pagination = pagination
 return r
}

func (r *response) Success(data interface{}) {
 r.Code = errcode.Success.Code()
 r.Msg = errcode.Success.Msg()
 requestId := ""
 if _, exists := r.ctx.Get("traceid"); exists {
  val, _ := r.ctx.Get("traceid")
  requestId = val.(string)
 }
 r.RequestId = requestId
 r.Data = data

 r.ctx.JSON(errcode.Success.HttpStatusCode(), r)
}

func (r *response) SuccessOk() {
 r.Success("")
}

func (r *response) Error(err *errcode.AppError) {
 r.Code = err.Code()
 r.Msg = err.Msg()
 requestId := ""
 if _, exists := r.ctx.Get("traceid"); exists {
  val, _ := r.ctx.Get("traceid")
  requestId = val.(string)
 }
 r.RequestId = requestId
 // 兜底記一條響應(yīng)錯(cuò)誤, 項(xiàng)目自定義的AppError中有錯(cuò)誤鏈條, 方便出錯(cuò)后排查問(wèn)題
 logger.New(r.ctx).Error("api_response_error", "err", err)
 r.ctx.JSON(err.HttpStatusCode(), r)
}
  • SetPagination 用來(lái)設(shè)置響應(yīng)的分頁(yè)信息
  • Success 返回接口執(zhí)行符合預(yù)期的成功響應(yīng),其中會(huì)攜帶Data數(shù)據(jù)返回給客戶端。
  • SuccessOk 針對(duì)只需要知道成功狀態(tài)的接口響應(yīng),目的是簡(jiǎn)化接口程序的調(diào)用。在這種情況下不需要使用一個(gè)空字符串或者nil參數(shù)去調(diào)用Success方法。
  • Error 返回錯(cuò)誤響應(yīng),參數(shù)為我們?yōu)轫?xiàng)目定義的AppError對(duì)象,這樣響應(yīng)碼使用的既是AppError的Code碼,在返回錯(cuò)誤響應(yīng)時(shí)會(huì)記錄一條錯(cuò)誤響應(yīng),這樣即使你在處理程序中沒(méi)有打錯(cuò)誤日志,框架這里也能做個(gè)兜底,方便出錯(cuò)后排查問(wèn)題。

接口響應(yīng)里的requestId 我們?nèi)〉氖钱?dāng)次請(qǐng)求對(duì)應(yīng)的tracceid這樣requestId 也能跟我們本次請(qǐng)求的所有日志中攜帶的traceid 對(duì)應(yīng)起來(lái),具體可參前面的文章Go日志門面的設(shè)計(jì)與實(shí)現(xiàn)-自動(dòng)注入追蹤ID。

用組件返回成功和錯(cuò)誤響應(yīng)

接下來(lái)我們?cè)陧?xiàng)目中寫幾個(gè)簡(jiǎn)單的接口測(cè)試一下組件的功能。

先寫一個(gè)返回返回對(duì)象信息的測(cè)試接口。

g.GET("/response-obj", func(c *gin.Context) {

  data := map[string]int{
   "a": 1,
   "b": 2,
  }
  app.NewResponse(c).Success(data)
  return
 })

運(yùn)行項(xiàng)目后訪問(wèn)接口會(huì)看到以下結(jié)果。

圖片圖片

再來(lái)一個(gè)返回錯(cuò)誤響應(yīng)的測(cè)試接口。

g.GET("/response-error", func(c *gin.Context) {

  baseErr := errors.New("a dao error")
  // 這一步正式開(kāi)發(fā)時(shí)寫在service層
  err := errcode.Wrap("encountered an error when xxx service did xxx", baseErr)
  app.NewResponse(c).Error(errcode.ErrServer.WithCause(err))
  return
 })

這里是Mock了一個(gè)錯(cuò)誤進(jìn)行了返回,運(yùn)行項(xiàng)目訪問(wèn)接口會(huì)看到下面的結(jié)果

圖片圖片

返回錯(cuò)誤響應(yīng)時(shí),我并沒(méi)有記錯(cuò)誤日志,但是的組件會(huì)幫我們兜底記了一條響應(yīng)錯(cuò)誤的日志, 防止開(kāi)發(fā)中忘了在程序中打錯(cuò)誤日志。

圖片 圖片

責(zé)任編輯:武曉燕 來(lái)源: 網(wǎng)管叨bi叨
相關(guān)推薦

2022-06-09 10:42:47

GoJSON

2024-12-17 09:14:48

項(xiàng)目http 庫(kù)API

2022-08-25 11:00:19

編程系統(tǒng)

2024-10-30 09:29:30

Go項(xiàng)目Error

2023-09-28 12:35:34

SQL數(shù)據(jù)庫(kù)系統(tǒng)

2025-02-05 08:43:40

2018-07-04 14:45:22

2025-03-07 09:01:14

商品模塊接口項(xiàng)目

2023-05-04 16:08:43

2010-06-01 14:47:18

SVN倉(cāng)庫(kù)目錄

2024-01-02 09:09:03

枚舉規(guī)范化管理

2010-09-07 15:53:02

CSS規(guī)范化

2022-05-20 07:48:14

API類型集成

2022-04-28 09:00:00

API集成Web

2009-01-13 10:50:19

數(shù)據(jù)庫(kù)設(shè)計(jì)規(guī)范化

2011-08-03 09:55:30

WindowsPowe組策略

2020-02-26 11:07:26

網(wǎng)絡(luò)5G技術(shù)

2010-09-08 16:49:05

CSSclassid

2024-10-06 13:49:30

2023-04-14 12:23:15

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)