首页 > 其他分享 >每日一库 swaggo

每日一库 swaggo

时间:2022-10-18 09:44:49浏览次数:79  
标签:-- 每日 一库 swaggo go gin swagger com

每日一库 swaggo

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

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

image

1.1关于swaggo

或许你使用过Swagger, 而 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为例

1.2使用

安装swag cli 及下载相关包

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

 go get -u -v github.com/swaggo/swag/cmd/swag

还需要下载两个包

# gin-swagger 中间件
go get github.com/swaggo/gin-swagger
# swagger 内置文件
go get github.com/swaggo/files

在main文件种添加注释

package main

import (
    "net/http"

    "github.com/gin-gonic/gin"
    _ "github.com/student/0509/docs"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
)

// @title Swagger Example API
// @version 1.0
// @description This is a sample server celler server.
// @termsOfService https://www.topgoer.com

// @contact.name www.topgoer.com
// @contact.url https://www.topgoer.com
// @contact.email [email protected]

// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html

// @host 127.0.0.1:8080
// @BasePath /api/v1

func main() {

    r := gin.Default()

    r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

    v1 := r.Group("/api/v1")
    {
        v1.GET("/hello", HandleHello)
        // v1.POST("/login", HandleLogin)
        // v1Auth := r.Use(HandleAuth)
        // {
        //     v1Auth.POST("/upload", HandleUpload)
        //     v1Auth.GET("/list", HandleList)
        // }
    }

    r.Run(":8080")
}

如上所示我们需要导入两个包

	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"

同时,添加注释。其中:

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

在项目目录下执行init生成文档

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

然后需要在main文件种导入生成的docs包

_ "项目路径/docs"

启动项目,浏览器打开http://127.0.0.1:8080/swagger/index.html, 我们可以看到如下文档标题已经生成。

image

1.1.3init的参数

$ swag init --help
NAME:
   swag init - Create docs.go
 
USAGE:
   swag init [command options] [arguments...]
 
OPTIONS:
   --generalInfo value, -g value          Go file path in which 'swagger general API Info' is written (default: "main.go")
   --dir value, -d value                  Directories you want to parse,comma separated and general-info file must be in the first one (default: "./")
   --exclude value                        Exclude directories and files when searching, comma separated
   --propertyStrategy value, -p value     Property Naming Strategy like snakecase,camelcase,pascalcase (default: "camelcase")
   --output value, -o value               Output directory for all the generated files(swagger.json, swagger.yaml and doc.go) (default: "./docs")
   --parseVendor                          Parse go files in 'vendor' folder, disabled by default (default: false)
   --parseDependency, --pd                Parse go files inside dependency folder, disabled by default (default: false)
   --markdownFiles value, --md value      Parse folder containing markdown files to use as description, disabled by default
   --codeExampleFiles value, --cef value  Parse folder containing code example files to use for the x-codeSamples extension, disabled by default
   --parseInternal                        Parse go files in internal packages, disabled by default (default: false)
   --generatedTime                        Generate timestamp at the top of docs.go, disabled by default (default: false)
   --parseDepth value                     Dependency parse depth (default: 100)
   --instanceName value                   This parameter can be used to name different swagger document instances. It is optional.
   --overridesFile value                  File to read global type overrides from. (default: ".swaggo")
   --help, -h                             show help (default: false)

选项 默认值 描述
-g main.go API通用信息所在Go源文件路径,若是相对路径则基于API解析目录。
-d ./ API解析目录
--exclude 空 解析扫描时排除的目录,多个目录可使用逗号分割。
-p camelcase 结构体字段命名规则,三种可选snakecase、camelcase、pascalcase。
-o ./docs 文件输出目录
--parseVendor 禁用 是否解析vendor目录中的Go源文件
--parseDependency 禁用 是否解析依赖目录中的Go源文件
--md - 指定API的描述信息所使用的MarkDown文件所在的目录
--generateTime 启用 是否输出时间到输出文件docs.go顶部
--cef 禁用 解析包含用于x-codeSamples扩展的代码示例文件的文件夹
--parseInternal 禁用 解析internal包中的Go文件
--parseDepth 100 依赖解析深度
--instanceName swagger 设置文档实例名称

若项目根目录下存在main.go主入口文件,可直接使用swag init初始化创建docs.go。若接口注释没有编写在默认的main.go主入口文件中,可使用-g标识来告知swag。

 swag init -g swag.go

1.1.4在API函数上添加注释

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

package main

import (
    "net/http"

    "github.com/gin-gonic/gin"
    _ "github.com/student/0509/docs"
    ginSwagger "github.com/swaggo/gin-swagger"
    "github.com/swaggo/gin-swagger/swaggerFiles"
)

// @title Swagger Example API
// @version 1.0
// @description This is a sample server celler server.
// @termsOfService https://www.topgoer.com

// @contact.name www.topgoer.com
// @contact.url https://www.topgoer.com
// @contact.email [email protected]

// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html

// @host 127.0.0.1:8080
// @BasePath /api/v1

func main() {

    r := gin.Default()

    r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

    v1 := r.Group("/api/v1")
    {
        v1.GET("/hello", HandleHello)
        // v1.POST("/login", HandleLogin)
        // v1Auth := r.Use(HandleAuth)
        // {
        //     v1Auth.POST("/upload", HandleUpload)
        //     v1Auth.GET("/list", HandleList)
        // }
    }

    r.Run(":8080")
}

// @Summary 测试SayHello
// @Description 向你说Hello
// @Tags 测试
// @Accept json
// @Param who query string true "人名"
// @Success 200 {string} string "{"msg": "hello Razeen"}"
// @Failure 400 {string} string "{"msg": "who are you"}"
// @Router /hello [get]
func HandleHello(c *gin.Context) {
    who := c.Query("who")

    if who == "" {
        c.JSON(http.StatusBadRequest, gin.H{"msg": "who are u?"})
        return
    }

    c.JSON(http.StatusOK, gin.H{"msg": "hello " + who})
}

重新swag init一下,运行一下。

此时,该API的相关描述已经生成了,我们点击Try it out还可以直接测试该API。

1.1.5字段解释

swaggo

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

Tags

Tags 是用来给API分组的。

Accept

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

Produce

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

Mime Type 声明
application/json json
text/xml xml
text/plain plain
html html
multipart/form-data mpfd
application/x-www-form-urlencoded x-www-form-urlencoded
application/vnd.api+json json-api
application/x-json-stream json-stream
application/octet-stream octet-stream
image/png png
image/jpeg jpeg
image/gif gif

Param

参数,从前往后分别是:

@Param 1.参数名 2.参数类型 3.参数数据类型 4.是否必须 5.参数描述 6.其他属性

  • 1.参数名

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

  • 2.参数类型

    参数类型主要有三种:

    • path 该类型参数直接拼接在URL中,如DemoHandleGetFile

      // @Param id path integer true "文件ID"
      
    • query 该类型参数一般是组合在URL中的,如DemoHandleHello

      // @Param who query string true "人名"
      
    • formData 该类型参数一般是POST,PUT方法所用,如DemoHandleLogin

      // @Param user formData string true "用户名" default(admin)
      
  • 3.参数数据类型

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

    • string (string)
    • integer (int, uint, uint32, uint64)
    • number (float32)
    • boolean (bool)

    注意,如果你是上传文件可以使用file, 但参数类型一定是formData, 如下:

    // @Param file formData file true "文件"
    
  • 4.是否是必须

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

  • 5.参数描述

    就是参数的一些说明

  • 6.其他属性

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

    枚举
    // @Param enumstring query string false "string enums" Enums(A, B, C)
    // @Param enumint query int false "int enums" Enums(1, 2, 3)
    // @Param enumnumber query number false "int enums" Enums(1.1, 1.2, 1.3)
    
    值添加范围
    // @Param string query string false "string valid" minlength(5) maxlength(10)
    // @Param int query int false "int valid" mininum(1) maxinum(10)
    
    设置默认值
    // @Param default query string false "string default" default(A)
    

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

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

    Success

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

// @Success 1.HTTP响应码 {2.响应参数类型} 3.响应数据类型 4.其他描述

  • 1.HTTP响应码

    也就是200,400,500那些。

  • 2.响应参数类型 / 3.响应数据类型

    返回的数据类型,可以是自定义类型,可以是json。

    • 自定义类型

    在平常的使用中,我都会返回一些指定的模型序列化JSON的数据,这时,就可以这么写:

    // @Success 200 {object} main.File
    

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

    // @Success 200 {anrry} main.File
    
    • json

    将如你只是返回其他的json数据可如下写:

    // @Success 200 {string} json ""
    
  • 4.其他描述

    可以添加一些说明。

Failure

同Success。

Router

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

// @Router /path/to/handle [HTTP方法]

不用加基础路径哦。

1.1.6生成测试文档

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

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

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

1.1.7 优化

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

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

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

package main

//...

var swagHandler gin.HandlerFunc

func main(){
    // ...

        if swagHandler != nil {
            r.GET("/swagger/*any", swagHandler)
        }

    //...
}

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

// +build doc

package main

import (
    _ "github.com/razeencheng/demo-go/swaggo-gin/docs"

    ginSwagger "github.com/swaggo/gin-swagger"
    "github.com/swaggo/gin-swagger/swaggerFiles"
)

func init() {
    swagHandler = ginSwagger.WrapHandler(swaggerFiles.Handler)
}

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

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

➜  swaggo-gin git:(master) ✗ go build
➜  swaggo-gin git:(master) ✗ ll swaggo-gin
-rwxr-xr-x  1 xxx  staff    15M Jan 13 00:23 swaggo-gin
➜  swaggo-gin git:(master) ✗ go build -tags "doc"
➜  swaggo-gin git:(master) ✗ ll swaggo-gin
-rwxr-xr-x  1 xxx  staff    34M Jan 13 00:24 swaggo-gin

1.1.8token

如果你的程序中使用了token中间键,只需要添加下面两行注释即可

// @Security x-token
// @param x-token header string true "Authorization"

列子:

// @Tags TASK
// @Summary 获取任务列表
// @Produce json
// @Accept json
// @Header 200 {string} Authorization "必备"
// @Param data body service.ListTasksService true "rush"
// @Success 200 {object} serializer.ResponseTask "{"success":true,"data":{},"msg":"ok"}"
// @Failure 500 {json} {"status":500,"data":{},"Msg":{},"Error":"error"}
// @Router /tasks [get]
func ListTasks(c *gin.Context) {
	listService := service.ListTasksService{}
	chaim, _ := util.ParseToken(c.GetHeader("Authorization"))
	if err := c.ShouldBind(&listService); err == nil {
		res := listService.List(chaim.Id)
		c.JSON(200, res)
	} else {
		c.JSON(400, ErrorResponse(err))
		util.LogrusObj.Info(err)
	}

标签:--,每日,一库,swaggo,go,gin,swagger,com
From: https://www.cnblogs.com/jingzhe2020/p/16801539.html

相关文章