1. Swaggo

    相信很多程序猿和我一样不喜欢写API文档。写代码多舒服,写文档不仅要花费大量的时间,有时候还不能做到面面具全。但API文档是必不可少的,相信其重要性就不用我说了,一份含糊的文档甚至能让前后端人员打起来。 而今天这篇博客介绍的swaggo就是让你只需要专注于代码就可以生成完美API文档的工具。废话说的有点多,我们直接看文章。

    大概最后文档效果是这样的:

    或许你使用过, 而 swaggo就是代替了你手动编写yaml的部分。只要通过一个命令就可以将注释转换成文档,这让我们可以更加专注于代码。

    目前swaggo主要实现了swagger 2.0 的以下部分功能:

    • 基本结构(Basic Structure)
    • API 地址与基本路径(API Host and Base Path)
    • 路径与操作 (Paths and Operations)
    • 参数描述(Describing Parameters)
    • 请求参数描述(Describing Request Body)
    • 返回描述(Describing Responses)
    • MIME 类型(MIME Types)
    • 认证(Authentication)
      • Basic Authentication
      • API Keys
    • 添加实例(Adding Examples)
    • 文件上传(File Upload)
    • 枚举(Enums)
    • 按标签分组(Grouping Operations With Tags)
    • 扩展(Swagger Extensions)

    下文内容均以gin-swaggo为例 这里是demo地址

    安装swag cli 及下载相关包

    要使用swaggo,首先需要安装swag cli。

    然后我们还需要两个包。

    1. go get github.com/swaggo/gin-swagger
    2. # swagger 内置文件
    3. go get github.com/swaggo/gin-swagger/swaggerFiles

    在main.go内添加注释

    1. package main
    2. import (
    3. "net/http"
    4. "github.com/gin-gonic/gin"
    5. _ "github.com/student/0509/docs"
    6. ginSwagger "github.com/swaggo/gin-swagger"
    7. "github.com/swaggo/gin-swagger/swaggerFiles"
    8. )
    9. // @title Swagger Example API
    10. // @version 1.0
    11. // @description This is a sample server celler server.
    12. // @termsOfService https://www.topgoer.com
    13. // @contact.name www.topgoer.com
    14. // @contact.url https://www.topgoer.com
    15. // @contact.email me@razeen.me
    16. // @license.name Apache 2.0
    17. // @license.url http://www.apache.org/licenses/LICENSE-2.0.html
    18. // @host 127.0.0.1:8080
    19. // @BasePath /api/v1
    20. func main() {
    21. r := gin.Default()
    22. r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
    23. v1 := r.Group("/api/v1")
    24. {
    25. v1.GET("/hello", HandleHello)
    26. // v1.POST("/login", HandleLogin)
    27. // v1Auth := r.Use(HandleAuth)
    28. // {
    29. // v1Auth.POST("/upload", HandleUpload)
    30. // v1Auth.GET("/list", HandleList)
    31. }
    32. r.Run(":8080")
    33. }

    如上所示,我们需要导入

    1. ginSwagger "github.com/swaggo/gin-swagger"
    2. "github.com/swaggo/gin-swagger/swaggerFiles"

    同时,添加注释。其中:

    • titile: 文档标题
    • version: 版本
    • description,termsOfService,contact … 这些都是一些声明,可不写。
    • license.name 额,这个是必须的。
    • host,BasePath: 如果你想直接swagger调试API,这两项需要填写正确。前者为服务文档的端口,ip。后者为基础路径,像我这里就是“/api/v1”。
    • 在原文档中还有securityDefinitions.basic,securityDefinitions.apikey等,这些都是用来做认证的,我这里暂不展开。

    到这里,我们在mian.go同目录下执行swag init就可以自动生成文档,如下:

    1. E:\goproject\src\github.com\topgoer>swag init
    2. 2020/05/13 16:28:02 Generate swagger docs....
    3. 2020/05/13 16:28:02 Generate general API Info, search dir:./
    4. 2020/05/13 16:28:02 create docs.go at docs/docs.go
    5. 2020/05/13 16:28:02 create swagger.json at docs/swagger.json
    6. 2020/05/13 16:28:02 create swagger.yaml at docs/swagger.yaml

    然后我们在main.go导入这个自动生成的docs包,运行:

    1. package main
    2. import (
    3. "github.com/gin-gonic/gin"
    4. ginSwagger "github.com/swaggo/gin-swagger"
    5. "github.com/swaggo/gin-swagger/swaggerFiles"
    6. _ "github.com/razeencheng/demo-go/swaggo-gin/docs"
    7. )
    8. // @title Swagger Example API
    9. // @version 1.0
    10. // ...

    浏览器打开, 我们可以看到如下文档标题已经生成。

    swaggo

    接下来,我们需要在每个路由处理函数上加上注释,如:

    1. package main
    2. import (
    3. "net/http"
    4. "github.com/gin-gonic/gin"
    5. _ "github.com/student/0509/docs"
    6. ginSwagger "github.com/swaggo/gin-swagger"
    7. "github.com/swaggo/gin-swagger/swaggerFiles"
    8. )
    9. // @title Swagger Example API
    10. // @version 1.0
    11. // @description This is a sample server celler server.
    12. // @termsOfService https://www.topgoer.com
    13. // @contact.name www.topgoer.com
    14. // @contact.url https://www.topgoer.com
    15. // @contact.email me@razeen.me
    16. // @license.name Apache 2.0
    17. // @license.url http://www.apache.org/licenses/LICENSE-2.0.html
    18. // @host 127.0.0.1:8080
    19. // @BasePath /api/v1
    20. func main() {
    21. r := gin.Default()
    22. r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
    23. v1 := r.Group("/api/v1")
    24. {
    25. v1.GET("/hello", HandleHello)
    26. // v1.POST("/login", HandleLogin)
    27. // v1Auth := r.Use(HandleAuth)
    28. // {
    29. // v1Auth.POST("/upload", HandleUpload)
    30. // v1Auth.GET("/list", HandleList)
    31. }
    32. r.Run(":8080")
    33. }
    34. // @Summary 测试SayHello
    35. // @Description 向你说Hello
    36. // @Tags 测试
    37. // @Accept json
    38. // @Param who query string true "人名"
    39. // @Success 200 {string} string "{"msg": "hello Razeen"}"
    40. // @Failure 400 {string} string "{"msg": "who are you"}"
    41. // @Router /hello [get]
    42. func HandleHello(c *gin.Context) {
    43. who := c.Query("who")
    44. if who == "" {
    45. return
    46. }
    47. c.JSON(http.StatusOK, gin.H{"msg": "hello " + who})
    48. }

    我们再次swag init, 运行一下。

    swaggo

    是不是很好用,当然这并没有结束,这些注释字段,我们一个个解释。

    这些注释对应出现在API文档的位置,我在上图中已经标出,这里我们主要详细说说下面参数:

    Tags

    Tags 是用来给API分组的。

    Accept

    接收的参数类型,支持表单(mpfd) 和 JSON(json)

    Produce

    返回的数据结构,一般都是json, 其他支持如下表:

    Param

    参数,从前往后分别是:

    • 1.参数名

    参数名就是我们解释参数的名字。

    • 2.参数类型

    参数类型主要有三种:

    • path 该类型参数直接拼接在URL中,如DemoHandleGetFile
    1. // @Param id path integer true "文件ID"
    • query 该类型参数一般是组合在URL中的,如中HandleHello
    1. // @Param who query string true "人名"
    • formData 该类型参数一般是POST,PUT方法所用,如DemoHandleLogin
    1. // @Param user formData string true "用户名" default(admin)
    • 3.参数数据类型

    数据类型主要支持一下几种:

    • string (string)
    • integer (int, uint, uint32, uint64)
    • number (float32)
    • boolean (bool)
      注意,如果你是上传文件可以使用file, 但参数类型一定是formData, 如下:
    1. // @Param file formData file true "文件"
    • 4.是否是必须

    表明该参数是否是必须需要的,必须的在文档中会黑体标出,测试时必须填写。

    • 5.参数描述

    就是参数的一些说明

    • 6.其他属性

    除了上面这些属性外,我们还可以为该参数填写一些额外的属性,如枚举,默认值,值范围等。如下:

    而且这些参数是可以组合使用的,如:

    1. // @Param enumstring query string false "string enums" Enums(A, B, C) default(A)

    Success

    指定成功响应的数据。格式为:

    • 1.HTTP响应码

    也就是200,400,500那些。

    • 2.响应参数类型 / 3.响应数据类型
    • 自定义类型
      在平常的使用中,我都会返回一些指定的模型序列化JSON的数据,这时,就可以这么写:
    1. // @Success 200 {object} main.File

    其中,模型直接用包名.模型即可。你会说,假如我返回模型数组怎么办?这时你可以这么写:

    1. // @Success 200 {anrry} main.File
    • json
      将如你只是返回其他的json数据可如下写:
    1. // @Success 200 {string} json ""
    • 4.其他描述

    可以添加一些说明。

    Failure

    ​ 同Success。

    Router

    ​ 指定路由与HTTP方法。格式为:

    ​ 不用加基础路径哦。

    其实上面已经穿插的介绍了。

    main.go下运行swag init即可生成和更新文档。

    点击文档中的Try it out即可测试。 如果部分API需要登陆,可以Try登陆接口即可。

    看到这里,基本可以使用了。但文档一般只是我们测试的时候需要,当我的产品上线后,接口文档是不应该给用户的,而且带有接口文档的包也会大很多(swaggo是直接build到二进制里的)。

    想要处理这种情况,我们可以在编译的时候优化一下,如利用build tag来控制是否编译文档。

    main.go声明swagHandler,并在该参数不为空时才加入路由:

    1. package main
    2. //...
    3. var swagHandler gin.HandlerFunc
    4. func main(){
    5. // ...
    6. if swagHandler != nil {
    7. r.GET("/swagger/*any", swagHandler)
    8. }
    9. //...
    10. }

    同时,我们将该参数在另外加了build tag的包中初始化。

    之后我们就可以使用go build -tags "doc"来打包带文档的包,直接go build来打包不带文档的包。

    你会发现,即使我这么小的Demo,编译后的大小也要相差19M !

    1. swaggo-gin git:(master) go build
    2. swaggo-gin git:(master) ll swaggo-gin
    3. -rwxr-xr-x 1 xxx staff 15M Jan 13 00:23 swaggo-gin
    4. swaggo-gin git:(master) go build -tags "doc"
    5. swaggo-gin git:(master) ll swaggo-gin

    文章到这里也就结束了,完整的。

    相关链接

    本文作者: Razeen

    本文链接: