使用go-swagger爲golang API自動生成swagger文檔

什麼是swagger?

Swagger是一個簡單但功能強大的API表達工具。它具備地球上最大的API工具生態系統,數以千計的開發人員,使用幾乎全部的現代編程語言,都在支持和使用Swagger。使用Swagger生成API,咱們能夠獲得交互式文檔,自動生成代碼的SDK以及API的發現特性等。html

swagger文檔長啥樣?

一個最簡單的swagger文檔示例:git

swagger: "2.0"

info:
 version: 1.0.0
 title: Simple API
 description: A simple API to learn how to write OpenAPI Specification

schemes:
 - https
host: simple.api
basePath: /openapi101

paths: {}
複製代碼

Tips:閱讀本文前提是假設你已經瞭解瞭如何編寫swagger文檔,固然,若是還不瞭解也不要緊,能夠去swagger官網查看文檔進行學習,而且這裏還有一套《Swagger從入門到精通》附上.程序員

本文背景介紹

​ 寫做本文的緣由是由於公司要求api文檔都使用 swagger格式,項目是用golang編寫的,做爲一個懶癌程序員,怎麼可以忍受去編寫這麼複雜的swagger文檔呢?有沒有一鍵生成的工具呢?google一下,還真有,那就是go-swagger項目。go-swagger衆多特點功能之一就是Generate a spec from source,即經過源碼生成文檔,很符合個人需求。github

下面就簡單介紹下如何爲項目加上swagger註釋,而後一鍵生成API文檔golang

開始以前須要安裝兩個工具:docker

  • swagger-editor:用於編寫swagger文檔,UI展現,生成代碼等...
  • go-swagger:用於一鍵生成API文檔

安裝swagger-editor,我這裏使用docker運行,其餘安裝方式,請查看官方文檔shell

docker pull swaggerapi/swagger-editor
docker run --rm -p 80:8080 swaggerapi/swagger-editor
複製代碼

安裝go-swagger,我這邊使用brew安裝,其餘安裝方式,請查看官方文檔編程

brew tap go-swagger/go-swagger
brew install go-swagger
複製代碼

好了,如今終於開始正題:start coding!!!json

開始編寫註釋

1.假設有一個user.server,提供一些REST API,用於對用戶數據的增刪改查。api

好比這裏有一個getOneUser接口,是查詢用戶信息的:

package service

import (
    "encoding/json"
    "fmt"
    "net/http"
    "strconv"
    "user.server/models"
    "github.com/Sirupsen/logrus"
)

type GetUserParam struct {
    Id int `json:"id"`
}

func GetOneUser(w http.ResponseWriter, r *http.Request) {
    defer r.Body.Close()
    decoder := json.NewDecoder(r.Body)
    var param GetUserParam
    err := decoder.Decode(&param)
    if err != nil {
        WriteResponse(w, ErrorResponseCode, "request param is invalid, please check!", nil)
        return
    }

    // get user from db
    user, err := models.GetOne(strconv.Itoa(param.Id))
    if err != nil {
        logrus.Warn(err)
        WriteResponse(w, ErrorResponseCode, "failed", nil)
        return
    }
    WriteResponse(w, SuccessResponseCode, "success", user)
}
複製代碼

根據swagger文檔規範,一個swagger文檔首先要有swagger的版本和info信息。利用go-swagger只須要在聲明package以前加上以下注釋便可:

// Package classification User API.
//
// The purpose of this service is to provide an application
// that is using plain go code to define an API
//
//      Host: localhost
//      Version: 0.0.1
//
// swagger:meta
package service
複製代碼

而後在項目根目錄下使用swagger generate spec -o ./swagger.json命令生成swagger.json文件:

此命令會找到main.go入口文件,而後遍歷全部源碼文件,解析而後生成swagger.json文件

{
  "swagger": "2.0",
  "info": {
    "description": "The purpose of this service is to provide an application\nthat is using plain go code to define an API",
    "title": "User API.",
    "version": "0.0.1"
  },
  "host": "localhost",
  "paths": {}
}
複製代碼

2.基本信息有了,而後就要有路由,請求,響應等,下面針對getOneUser接口編寫swagger註釋:

// swagger:parameters getSingleUser
type GetUserParam struct {
    // an id of user info
    //
    // Required: true
    // in: path
    Id int `json:"id"`
}

func GetOneUser(w http.ResponseWriter, r *http.Request) {
    // swagger:route GET /users/{id} users getSingleUser
    //
    // get a user by userID
    //
    // This will show a user info
    //
    // Responses:
    // 200: UserResponse
    decoder := json.NewDecoder(r.Body)
    var param GetUserParam
    err := decoder.Decode(&param)
    if err != nil {
        WriteResponse(w, ErrorResponseCode, "request param is invalid, please check!", nil)
        return
    }

    // get user from db
    user, err := models.GetOne(strconv.Itoa(param.Id))
    if err != nil {
        logrus.Warn(err)
        WriteResponse(w, ErrorResponseCode, "failed", nil)
        return
    }
    WriteResponse(w, SuccessResponseCode, "success", user)
}
複製代碼

能夠看到在GetUserParam結構體上面加了一行swagger:parameters getSingleUser的註釋信息,這是聲明接口的入參註釋,結構體內部的幾行註釋指明瞭id這個參數必填,而且查詢參數id是在url path中。詳細用法,參考: swagger:params

GetOneUser函數中:

  • swagger:route指明使用的http method,路由,以及標籤和operation id,詳細用法,參考: swagger:route
  • Responses指明瞭返回值的code以及類型

而後再聲明響應:

// User Info
//
// swagger:response UserResponse
type UserWapper struct {
    // in: body
    Body ResponseMessage
}

type ResponseMessage struct {
    Code    int         `json:"code"`
    Message string      `json:"message"`
    Data    interface{} `json:"data"`
}
複製代碼

使用swagger:response語法聲明返回值,其上兩行是返回值的描述(我也不清楚,爲啥描述信息要寫在上面,歡迎解惑),詳細用法,參考; swagger:response

而後瀏覽器訪問localhost,查看swagger-editor界面,點擊工具欄中的File->Impoprt File上傳剛纔生成的 swagger.json文件,就能夠看到界面:

這樣一個簡單的api文檔就生成了

3.怎麼樣?是否是很簡單?但是又感受那裏不對,嗯,註釋都寫在代碼裏了,很不美觀,並且不易維護。想一下go-swagger的原理是掃描目錄下的全部go文件,解析註釋信息。那麼是否是能夠把api註釋都集中寫在單個文件內,統一管理,省得分散在各個源碼文件內。

新建一個doc.go文件,這裏還有一個接口是UpdateUser,那麼咱們在doc.go文件中聲明此接口的api註釋。先看一下UpdateUser接口的代碼:

func UpdateUser(w http.ResponseWriter, r *http.Request) {
    defer r.Body.Close()
    // decode body data into user struct
    decoder := json.NewDecoder(r.Body)
    user := models.User{}
    err := decoder.Decode(&user)
    if err != nil {
        WriteResponse(w, ErrorResponseCode, "user data is invalid, please check!", nil)
        return
    }

    // check if user exists
    data, err := models.GetUserById(user.Id)
    if err != nil {
        logrus.Warn(err)
        WriteResponse(w, ErrorResponseCode, "query user failed", nil)
        return
    }
    if data.Id == 0 {
        WriteResponse(w, ErrorResponseCode, "user not exists, no need to update", nil)
        return
    }

    // update
    _, err = models.Update(user)
    if err != nil {
        WriteResponse(w, ErrorResponseCode, "update user data failed, please try again!", nil)
        return
    }
    WriteResponse(w, SuccessResponseCode, "update user data success!", nil)
}
複製代碼

而後再doc.go文件中編寫以下聲明:

package service

import "user.server/models"

// swagger:parameters UpdateUserResponseWrapper
type UpdateUserRequest struct {
    // in: body
    Body models.User
}

// Update User Info
//
// swagger:response UpdateUserResponseWrapper
type UpdateUserResponseWrapper struct {
    // in: body
    Body ResponseMessage
}

// swagger:route POST /users users UpdateUserResponseWrapper
//
// Update User
//
// This will update user info
//
// Responses:
// 200: UpdateUserResponseWrapper
複製代碼

這樣就把api聲明註釋給抽離出來了,而後使用命令swagger generate spec -o ./swagger.json生成json文件,就能夠看到這樣的結果:

很簡單吧,參照文檔編寫幾行註釋,而後一個命令生成API文檔。懶癌程序員福音~

本文全部示例代碼託管在這裏, 原文地址

參考:

相關文章
相關標籤/搜索