golang restful 框架之 go-swagger
restful 是這些年的高頻詞彙了,各大網際網路公司也都紛紛推出了自己的 restful api,其實 restful 和 thrift,grpc 類似,就是一種協議,但是這種協議有點特殊的就是使用 http 介面,返回的物件一般是 json 格式,這樣有個好處,就是可以供前端的 js 直接呼叫,使用非常方便,但 http 本身並不是一個高效的協議,後端的內部通訊還是使用 grpc 或者 thrift 可以獲得更高的效能
其實如果只是要用 http 返回 json 本身並不是一件很難的事情,不用任何框架,golang 本身也能很方便做到,但是當你有很多 api 的時候,這些 api 的維護和管理就會變得很複雜,你自己都無法記住這些 api 應該填什麼引數,返回什麼,當然你可以花很多時間去維護一份介面文件,這樣不僅耗時而且很難保證文件的即時性,準確性以及一致性
swagger 有一整套規範來定義一個介面檔案,類似於 thrift 和 proto 檔案,定義了服務的請求內容和返回內容,同樣也有工具可以生成各種不同語言的框架程式碼,在 golang 裡面我們使用 go-swagger 這個工具,這個工具還提供了額外的功能,可以視覺化顯示這個介面,方便閱讀
go-swagger 使用方法
api 定義檔案
首先需要寫一個 api 定義檔案,這裡我只展示其中一個介面 countlike
,請求中帶有某篇文章,返回點讚的次數
paths:
/countlike:
get:
tags:
- like
summary: 有多少贊
description: ''
operationId: countLike
consumes:
- application/json
produces:
- application/json
parameters:
- name: title
in: query
description: 文章標題
required: true
type: string
responses:
'200':
description: 成功
schema:
$ref : '#/definitions/CountLikeModel'
'500':
description: 內部錯誤
schema:
$ref: '#/definitions/ErrorModel'
definitions:
CountLikeModel:
type: object
properties:
count:
type: integer
title:
type: string
example: golang json 效能分析
ErrorModel:
type: object
properties:
message:
type: string
example: error message
code:
type: integer
example: 400
這個是 yaml 語法,有點像去掉了括號的 json
這裡完整地定義了請求方法、請求引數、正常返回介面、異常返回結果,有了這個檔案只需要執行下面命令就能生成框架程式碼了
swagger generate server -f api/comment_like/comment_like.yaml
還可以下面這個命令視覺化檢視這個介面檔案
swagger serve api/comment_like/comment_like.yaml
這個命令依賴 swagger 工具,可以通過下面命令獲取
Mac
brew tap go-swagger/go-swagger
brew install go-swagger
Linux
go get -u github.com/go-swagger/go-swagger/cmd/swagger
export PATH=$GOPATH/bin:$PATH
執行完了之後,你發現多了幾個資料夾,其中 cmd
目錄裡面包含 main 函式,是整個程式的入口,restapi
資料夾下面包含協議相關程式碼,其中 configure_xxx.go
是需要特別關注的,你需要在這個檔案裡面實現你具體的業務邏輯
現在你就其實已經可以執行程式了,go run cmd/comment-like-server/main.go
,在瀏覽器裡面訪問一下你的 api,會返回一個錯誤資訊,告訴你 api 還沒有實現,下面就來實現一下吧
業務邏輯實現
api.LikeCountLikeHandler = like.CountLikeHandlerFunc(func(params like.CountLikeParams) middleware.Responder {
count, err := comment_like.CountLike(params.Title)
if err != nil {
return like.NewCountLikeInternalServerError().WithPayload(&models.ErrorModel{
Code: http.StatusInternalServerError,
Message: err.Error(),
})
}
return like.NewCountLikeOK().WithPayload(&models.CountLikeModel{
Count: count,
Title: params.Title,
})
})
你只需要在這些 handler 裡面實現自己的業務邏輯即可,這裡對協議的封裝非常好,除了業務邏輯以及打包返回,沒有多餘的邏輯
再次執行,現在返回已經正常了
統一處理
如果你對請求有一些操作需要統一處理,比如輸出統一的日誌之類的,可以重寫這個函式,也在 configure_xxx.go
這個檔案中
func setupGlobalMiddleware(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
handler.ServeHTTP(w, r)
})
}
這裡我統一設定了一下頭部,解決跨域訪問問題