使用go-swagger为golang API自动生成swagger文档

Posted Golang语言社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用go-swagger为golang API自动生成swagger文档相关的知识,希望对你有一定的参考价值。



什么是swagger?


Swagger是一个简单但功能强大的API表达工具。它具有地球上最大的API工具生态系统,数以千计的开发人员,使用几乎所有的现代编程语言,都在支持和使用Swagger。使用Swagger生成API,我们可以得到交互式文档,自动生成代码的SDK以及API的发现特性等。


swagger文档长啥样?


一个最简单的swagger文档示例:


 1swagger: "2.0"
2info:
3  version: 1.0.0
4  title: Simple API
5  description: A simple API to learn how to write OpenAPI Specification
6schemes:
7  - https
8host: simple.api
9basePath: /openapi101
10paths: {}

Tips:阅读本文前提是假设你已经了解了如何编写swagger文档,当然,如果还不了解也没关系,可以去swagger官网查看文档进行学习,并且这里还有一套《Swagger从入门到精通》附上.


本文背景介绍


写作本文的原因是因为公司要求api文档都使用 swagger格式,项目是用golang编写的,作为一个懒癌程序员,怎么能够忍受去编写这么复杂的swagger文档呢?有没有一键生成的工具呢?google一下,还真有,那就是go-swagger项目。go-swagger众多特色功能之一就是Generate a spec from source,即通过源码生成文档,很符合我的需求。


下面就简单介绍下如何为项目加上swagger注释,然后一键生成API文档。


开始之前需要安装两个工具:


  • swagger-editor:用于编写swagger文档,UI展示,生成代码等...

  • go-swagger:用于一键生成API文档


安装swagger-editor,我这里使用docker运行,其他安装方式,请查看官方文档:


1docker pull swaggerapi/swagger-editor
2docker run --rm -p 80:8080 swaggerapi/swagger-editor


安装go-swagger,我这边使用brew安装,其他安装方式,请查看官方文档:


1brew tap go-swagger/go-swagger
2brew install go-swagger


好了,现在终于开始正题:start coding!!!

开始编写注释

1.假设有一个user.server,提供一些REST API,用于对用户数据的增删改查。

比如这里有一个getOneUser接口,是查询用户信息的:

 1package service
2import (
3    "encoding/json"
4    "fmt"
5    "net/http"
6    "strconv"
7    "user.server/models"
8    "github.com/Sirupsen/logrus"
9)
10type GetUserParam struct {
11    Id int `json:"id"`
12}
13func GetOneUser(w http.ResponseWriter, r *http.Request) {
14    defer r.Body.Close()
15    decoder := json.NewDecoder(r.Body)
16    var param GetUserParam
17    err := decoder.Decode(&param)
18    if err != nil {
19        WriteResponse(w, ErrorResponseCode, "request param is invalid, please check!", nil)
20        return
21    }
22    // get user from db
23    user, err := models.GetOne(strconv.Itoa(param.Id))
24    if err != nil {
25        logrus.Warn(err)
26        WriteResponse(w, ErrorResponseCode, "failed", nil)
27        return
28    }
29    WriteResponse(w, SuccessResponseCode, "success", user)
30}


根据swagger文档规范,一个swagger文档首先要有swagger的版本和info信息。利用go-swagger只需要在声明package之前加上如下注释即可:


 1// Package classification User API.
2//
3// The purpose of this service is to provide an application
4// that is using plain go code to define an API
5//
6//      Host: localhost
7//      Version: 0.0.1
8//
9// swagger:meta
10package service


然后在项目根目录下使用swagger generate spec -o ./swagger.json命令生成swagger.json文件:

此命令会找到main.go入口文件,然后遍历所有源码文件,解析然后生成swagger.json文件

 1{
2  "swagger": "2.0",
3  "info": {
4    "description": "The purpose of this service is to provide an application\nthat is using plain go code to define an API",
5    "title": "User API.",
6    "version": "0.0.1"
7  },
8  "host": "localhost",
9  "paths": {}
10}


2.基本信息有了,然后就要有路由,请求,响应等,下面针对getOneUser接口编写swagger注释:


 1// swagger:parameters getSingleUser
2type GetUserParam struct {
3    // an id of user info
4    //
5    // Required: true
6    // in: path
7    Id int `json:"id"`
8}
9func GetOneUser(w http.ResponseWriter, r *http.Request) {
10    // swagger:route GET /users/{id} users getSingleUser
11    //
12    // get a user by userID
13    //
14    // This will show a user info
15    //
16    //     Responses:
17    //       200: UserResponse
18    decoder := json.NewDecoder(r.Body)
19    var param GetUserParam
20    err := decoder.Decode(&param)
21    if err != nil {
22        WriteResponse(w, ErrorResponseCode, "request param is invalid, please check!", nil)
23        return
24    }
25    // get user from db
26    user, err := models.GetOne(strconv.Itoa(param.Id))
27    if err != nil {
28        logrus.Warn(err)
29        WriteResponse(w, ErrorResponseCode, "failed", nil)
30        return
31    }
32    WriteResponse(w, SuccessResponseCode, "success", user)
33}


可以看到在GetUserParam结构体上面加了一行swagger:parameters getSingleUser的注释信息,这是声明接口的入参注释,结构体内部的几行注释指明了id这个参数必填,并且查询参数id是在url path中。详细用法,参考: swagger:params

GetOneUser函数中:

  • swagger:route指明使用的http method,路由,以及标签和operation id,详细用法,参考: swagger:route

  • Responses指明了返回值的code以及类型

然后再声明响应:


 1// User Info
2//
3// swagger:response UserResponse
4type UserWapper struct {
5    // in: body
6    Body ResponseMessage
7}
8type ResponseMessage struct {
9    Code    int         `json:"code"`
10    Message string      `json:"message"`
11    Data    interface{} `json:"data"`
12}


使用swagger:response语法声明返回值,其上两行是返回值的描述(我也不清楚,为啥描述信息要写在上面,欢迎解惑),详细用法,参考; swagger:response

然后浏览器访问localhost,查看swagger-editor界面,点击工具栏中的File->Impoprt File上传刚才生成的 swagger.json文件,就可以看到界面:


使用go-swagger为golang API自动生成swagger文档


这样一个简单的api文档就生成了

3.怎么样?是不是很简单?可是又感觉那里不对,嗯,注释都写在代码里了,很不美观,而且不易维护。想一下go-swagger的原理是扫描目录下的所有go文件,解析注释信息。那么是不是可以把api注释都集中写在单个文件内,统一管理,免得分散在各个源码文件内。

新建一个doc.go文件,这里还有一个接口是UpdateUser,那么我们在doc.go文件中声明此接口的api注释。先看一下UpdateUser接口的代码:


 1func UpdateUser(w http.ResponseWriter, r *http.Request) {
2    defer r.Body.Close()
3    // decode body data into user struct
4    decoder := json.NewDecoder(r.Body)
5    user := models.User{}
6    err := decoder.Decode(&user)
7    if err != nil {
8        WriteResponse(w, ErrorResponseCode, "user data is invalid, please check!", nil)
9        return
10    }
11    // check if user exists
12    data, err := models.GetUserById(user.Id)
13    if err != nil {
14        logrus.Warn(err)
15        WriteResponse(w, ErrorResponseCode, "query user failed", nil)
16        return
17    }
18    if data.Id == 0 {
19        WriteResponse(w, ErrorResponseCode, "user not exists, no need to update", nil)
20        return
21    }
22    // update
23    _, err = models.Update(user)
24    if err != nil {
25        WriteResponse(w, ErrorResponseCode, "update user data failed, please try again!", nil)
26        return
27    }
28    WriteResponse(w, SuccessResponseCode, "update user data success!", nil)
29}


然后再doc.go文件中编写如下声明:


 1package service
2import "user.server/models"
3// swagger:parameters UpdateUserResponseWrapper
4type UpdateUserRequest struct {
5    // in: body
6    Body models.User
7}
8// Update User Info
9//
10// swagger:response UpdateUserResponseWrapper
11type UpdateUserResponseWrapper struct {
12    // in: body
13    Body ResponseMessage
14}
15// swagger:route POST /users users UpdateUserResponseWrapper
16//
17// Update User
18//
19// This will update user info
20//
21//     Responses:
22//       200: UpdateUserResponseWrapper


这样就把api声明注释给抽离出来了,然后使用命令swagger generate spec -o ./swagger.json生成json文件,就可以看到这样的结果:


使用go-swagger为golang API自动生成swagger文档

很简单吧,参照文档编写几行注释,然后一个命令生成API文档。懒癌程序员福音~

参考:

  • swagger官方Doc

  • Swagger从入门到精通

  • go-swagger文档

  • go-swagger的github主页


版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。



Golang语言社区

ID:Golangweb

游戏服务器架构丨分布式技术丨大数据丨游戏算法学习



以上是关于使用go-swagger为golang API自动生成swagger文档的主要内容,如果未能解决你的问题,请参考以下文章

Go开源宝藏Go-Swagger 自动生成 api 接口文档

golang restful 框架之 go-swagger

语言实践Go语言文档自动化之go-swagger

有啥方法可以使用 golang api 为 pod 设置节点选择器

golang程序通过docker打包到harbor的方式进行jenkins自动化发布

golang程序通过docker打包到harbor的方式进行jenkins自动化发布