Gin學(xué)習(xí)

Gin學(xué)習(xí)

  1. go-swagger

  2. Gin-APi json

1 go-swagger

前言

在前后端分離的項(xiàng)目開發(fā)過程中,如果后端同學(xué)能夠提供一份清晰明了的接口文檔,那么就能極大地提高大家的溝通效率和開發(fā)效率。那如何維護(hù)接口文檔,歷來都是令人頭痛的,感覺很浪費(fèi)精力,而且后續(xù)接口文檔的維護(hù)也十分耗費(fèi)精力。在很多年以前,也流行用word等工具寫接口文檔,這里面的問題很多,如格式不統(tǒng)一、后端人員消費(fèi)精力大、文檔的時(shí)效性也無法保障。

針對(duì)這類問題,最好是有一種方案能夠既滿足我們輸出文檔的需要又能隨代碼的變更自動(dòng)更新,Swagger正是那種能幫我們解決接口文檔問題的工具。

Swagger介紹

Swagger是基于標(biāo)準(zhǔn)的 OpenAPI 規(guī)范進(jìn)行設(shè)計(jì)的,本質(zhì)是一種用于描述使用json表示的Restful Api的接口描述語(yǔ)言,只要照著這套規(guī)范去編寫你的注解或通過掃描代碼去生成注解,就能生成統(tǒng)一標(biāo)準(zhǔn)的接口文檔和一系列 Swagger 工具。Swagger包括自動(dòng)文檔,代碼生成和測(cè)試用例生成。

安裝Swagger

1、安裝

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="arduino" cid="n15" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">arduino
復(fù)制代碼go get -u github.com/swaggo/swag/cmd/swag</pre>

在macOS中安裝 swag需要執(zhí)行如下命令:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="bash" cid="n17" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">bash
復(fù)制代碼mv $GOPATH/bin/swag /usr/local/go/bin</pre>

2、檢測(cè)是否安裝成功

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="ruby" cid="n19" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">ruby復(fù)制代碼$ swag -v
swag version v1.8.4</pre>

3、安裝gin-swagger擴(kuò)展

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="shell" cid="n21" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">shell復(fù)制代碼go get -u -v github.com/swaggo/gin-swagger go get -u -v github.com/swaggo/files
$ go get -u -v github.com/alecthomas/template</pre>

使用

使用gin-swagger為你的代碼自動(dòng)生成接口文檔,一般需要下面三個(gè)步驟:

  1. 按照swagger要求給接口代碼添加聲明式注釋。

  2. 使用swag工具掃描代碼自動(dòng)生成api接口文檔數(shù)據(jù)。

  3. 使用gin-swagger渲染在線接口文檔頁(yè)面。

1、添加注釋

go-swapper注解規(guī)范說明:

注:注解詳情可參見官網(wǎng)文檔Swagger Documentation

注解 描述
@Summary 摘要
@Produce API 可以產(chǎn)生的 MIME 類型的列表,MIME 類型你可以簡(jiǎn)單的理解為響應(yīng)類型,例如:json、xml、html 等等
@Param 參數(shù)格式,從左到右分別為:參數(shù)名、入?yún)㈩愋汀?shù)據(jù)類型、是否必填、注釋
@Success 響應(yīng)成功,從左到右分別為:狀態(tài)碼、參數(shù)類型、數(shù)據(jù)類型、注釋
@Failure 響應(yīng)失敗,從左到右分別為:狀態(tài)碼、參數(shù)類型、數(shù)據(jù)類型、注釋
@Router 路由,從左到右分別為:路由地址,HTTP 方法

參數(shù)類型Param Type

  • object (struct)

  • string (string)

  • integer (int, uint, uint32, uint64)

  • number (float32)

  • boolean (bool)

  • array

數(shù)據(jù)類型Data Type

  • string (string)

  • integer (int, uint, uint32, uint64)

  • number (float32)

  • boolean (bool)

  • user defined struct

示例demo:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="sql" cid="n83" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">sql復(fù)制代碼package main

import (
"github.com/gin-gonic/gin"
"github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
_ "github/mwqnice/swag/docs" // 千萬不要忘了導(dǎo)入把你上一步生成的docs
)

type Article struct{
ID uint32 gorm:"primary_key" json:"id"
CreatedBy string json:"created_by"
ModifiedBy string json:"modified_by"
CreatedOn uint32 json:"created_on"
ModifiedOn uint32 json:"modified_on"
DeletedOn uint32 json:"deleted_on"
IsDel uint8 json:"is_del"
Title string json:"title"
Desc string json:"desc"
Content string json:"content"
CoverImageUrl string json:"cover_image_url"
State uint8 json:"state"
}

func NewArticle() Article {
return Article{}
}

func main() {
r := gin.Default()
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
r.Run(":8088")
}

// @Summary 獲取單個(gè)文章
// @Produce json
// @Param id path int true "文章ID"
// @Success 200 {object} Article "成功"
// @Failure 400 {object} string "請(qǐng)求錯(cuò)誤"
// @Failure 500 {object} string "內(nèi)部錯(cuò)誤"
// @Router /api/v1/articles/{id} [get]
func (a Article) Get(c *gin.Context) {

}

// @Summary 獲取多個(gè)文章
// @Produce json
// @Param name query string false "文章名稱"
// @Param tag_id query int false "標(biāo)簽ID"
// @Param state query int false "狀態(tài)"
// @Param page query int false "頁(yè)碼"
// @Param page_size query int false "每頁(yè)數(shù)量"
// @Success 200 {object} Article "成功"
// @Failure 400 {object} string "請(qǐng)求錯(cuò)誤"
// @Failure 500 {object} string "內(nèi)部錯(cuò)誤"
// @Router /api/v1/articles [get]
func (a Article) List(c *gin.Context) {
return
}

// @Summary 創(chuàng)建文章
// @Produce json
// @Param tag_id body string true "標(biāo)簽ID"
// @Param title body string true "文章標(biāo)題"
// @Param desc body string false "文章簡(jiǎn)述"
// @Param cover_image_url body string true "封面圖片地址"
// @Param content body string true "文章內(nèi)容"
// @Param created_by body int true "創(chuàng)建者"
// @Param state body int false "狀態(tài)"
// @Success 200 {object} Article "成功"
// @Failure 400 {object} string "請(qǐng)求錯(cuò)誤"
// @Failure 500 {object} string "內(nèi)部錯(cuò)誤"
// @Router /api/v1/articles [post]
func (a Article) Create(c *gin.Context) {

}

// @Summary 更新文章
// @Produce json
// @Param tag_id body string false "標(biāo)簽ID"
// @Param title body string false "文章標(biāo)題"
// @Param desc body string false "文章簡(jiǎn)述"
// @Param cover_image_url body string false "封面圖片地址"
// @Param content body string false "文章內(nèi)容"
// @Param modified_by body string true "修改者"
// @Success 200 {object} Article "成功"
// @Failure 400 {object} string "請(qǐng)求錯(cuò)誤"
// @Failure 500 {object} string "內(nèi)部錯(cuò)誤"
// @Router /api/v1/articles/{id} [put]
func (a Article) Update(c *gin.Context) {
return
}

// @Summary 刪除文章
// @Produce json
// @Param id path int true "文章ID"
// @Success 200 {string} string "成功"
// @Failure 400 {object} string "請(qǐng)求錯(cuò)誤"
// @Failure 500 {object} string "內(nèi)部錯(cuò)誤"
// @Router /api/v1/articles/{id} [delete]
func (a Article) Delete(c *gin.Context) {
return
}</pre>

2、生成接口文檔數(shù)據(jù)

格式化swag注解

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="shell" cid="n86" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">shell
復(fù)制代碼$ swag fmt</pre>

在項(xiàng)目根目錄執(zhí)行以下命令,使用swag工具生成接口文檔數(shù)據(jù)。

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="csharp" cid="n88" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">csharp
復(fù)制代碼$ swag init</pre>

執(zhí)行完上述命令后,如果你寫的注釋格式?jīng)]問題,此時(shí)你的項(xiàng)目根目錄下會(huì)多出一個(gè)docs文件夾。

./docs

├── docs.go

├── swagger.json

└── swagger.yaml

3、引入gin-swagger渲染文檔數(shù)據(jù)

然后在項(xiàng)目代碼中注冊(cè)路由的地方按如下方式引入gin-swagger相關(guān)內(nèi)容:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="go" cid="n96" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">go復(fù)制代碼import (
"github.com/gin-gonic/gin"
"github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
_ "github/mwqnice/swag/docs" // 千萬不要忘了導(dǎo)入把你上一步生成的docs
)
//添加swagger訪問路由
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))</pre>

啟動(dòng)項(xiàng)目,在瀏覽器中輸入地址:http://127.0.0.1:8088/swagger/index.html

2 Gin-APi json

方法1:

基于GetRawData()map獲取。

示例:

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="go" cid="n103" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">//需要導(dǎo)入包
import (
"encoding/json"
"github.com/gin-gonic/gin"
)

// Login 假如有一個(gè)用戶登錄接口
func Login(c *gin.Context) {
data, _ := c.GetRawData()
var body map[string]string
_ = json.Unmarshal(data, &body)

//獲取json中的key,注意使用["key"]獲取
name:= body["name"]
email := body["email"]

}</pre>


方法2:(推薦使用)

基于BindJSON()結(jié)構(gòu)體獲取。

通過BindJSON()可見將json請(qǐng)求體綁定到一個(gè)結(jié)構(gòu)體上。(通常綁定到一個(gè)匿名結(jié)構(gòu)體)

示例:

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="go" cid="n109" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">//需要導(dǎo)入包
import (
"github.com/gin-gonic/gin"
)

// Login 假如有一個(gè)用戶登錄接口
func Login(c *gin.Context) {
//定義匿名結(jié)構(gòu)體,字段與json字段對(duì)應(yīng)
var body struct {
Email string json:"email"
Name string json:"name"
}

//綁定json和結(jié)構(gòu)體
if err := c.BindJSON(&body); err != nil {
    return
}
//獲取json中的key,注意使用 . 訪問
email := body.Email
name := body.Name

}</pre>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容