Swagger学习笔记(基于Go-Gin)

news/2024/7/24 4:48:21 标签: restful, go, swagger2

文章目录

  • Swagger学习(基于Go-Gin框架)
    • 狂神说Swagger
      • 小结
    • 李文周Swagger
      • Swagger介绍
        • 第一步: 添加注释
        • 第二步:生成接口文档数据
        • 第三步:引入gin-swagger渲染文档数据
      • 小结
    • go中文文档中的Swaggo
      • 介绍
      • 使用
        • 全局配置各项参数的作用
        • 各个接口的注释参数作用
          • `Tags`
          • `Accept`
          • `Produce`
          • `Param`
            • 参数类型
            • 参数数据类型
            • 是否是必须
            • 参数描述
            • 其他属性
          • ```Success```
          • Router
      • 生成文档与测试
      • 优化
      • 如果使用了Token
    • swag-go说明文档(git hub)
      • 快速开始
      • 支持的框架
      • 声明式注释格式
        • main.go上通用API信息
        • 使用markdown描述
        • API注释
        • Mime类型
      • 参数类型
      • 数据类型
      • 安全性
      • 小结
    • 参考资料

Swagger学习(基于Go-Gin框架)

在Swagger的学习中,我找了比较多的资料下面采取的学习路线是:

《狂神说Swagger》-> 李文周博客 -> 网上博主资料总结 -> 官方说明文档

只有第一个是视频,因为我感觉视频有一种手把手的教学的感觉,可以很好的让你入门,但是它有它的弊端,比如效率太低,讲的不够深入和全面等。

我个人认为学习一个技术,全面的了解过一遍,还是很有必要的,这是视频所无法给予的,所以后面的文档学习安排也是难度逐次递进的。

狂神说Swagger

在前端可以通过这种方式来伪造数据

image-20210916183814321

Swagger号称世界上最流行的Api框架

RestFul APi文档在线自动生成工具=>api文档与api定义同步更新

可以直接运行在线测试api接口

image-20210916184138912 image-20210916184145197 image-20210916184149464

小结

狂神说的swagger视频只是浅尝辄止了一下,也并没有讲的太深,带着我们把swagger入门了一下,不过我感觉这个教程的效果对于部分人而言可能不是很好,但是他提供了一个很好的学习的思路,他学习swagger是通过查看swagger包的源代码学习的,在没有很好的教程的时候,我们也可以采用这种方式去学习,但是这样的教程会感觉是在跳来跳去的,如果你的代码能力不是很精通的话,可能会对我们学习Swagger有附加的理解难度。

于是我就简单了解了一下,就跳过了这个视频的学习,不过也知道了一些基本的内容。

李文周Swagger

Swagger介绍

本质上是用JSON表示的RESTful API的接口描述语言。 Swagger包括自动文档,代码生成和测试用例生成。

在前后端分离的项目开发过程中,如果后端同学能够提供一份清晰明了的接口文档,那么就能极大地提高大家的沟通效率和开发效率。可是编写接口文档历来都是令人头痛的,而且后续接口文档的维护也十分耗费精力。

最好是有一种方案能够既满足我们输出文档的需要又能随代码的变更自动更新,而Swagger正是那种能帮我们解决接口文档问题的工具。

而我们以Gin框架为例,使用gin-swagger库,使用Swagger 2.0生成RESTful API文档

使用gin-swagger一般需要下面三个步骤:

  1. 按照swagger要求给接口代码添加声明式注释,具体参照声明式注释格式。
  2. 使用swag工具扫描代码自动生成API接口文档数据
  3. 使用gin-swagger渲染在线接口文档页面

第一步: 添加注释

在程序入口main函数上以注释的形式写下项目相关的介绍信息

这个算是全局配置,在swagger的最上面会显示出来,在实际的项目开发中,作用不是很大。

image-20210916191651930

image-20210916191750540

第二步:生成接口文档数据

使用下面的命令来安装swag工具

go">go get -u github.com/swaggo/swag/cmd/swag

在项目根目录执行以下命令来通过swag工具生成接口文档数据

go">swag init

执行完命令之后,如果我们之前的配置写的没有问题,项目根目录下会多出一个docs文件夹。

go">./docs
├── docs.go
├── swagger.json
└── swagger.yaml

第三步:引入gin-swagger渲染文档数据

然后在项目代码中注册路由的地方按如下方式引入gin-swagger相关内容:

go">import (
	// liwenzhou.com ...

	_ "bluebell/docs"  // 千万不要忘了导入把你上一步生成的docs

	gs "github.com/swaggo/gin-swagger"
	"github.com/swaggo/gin-swagger/swaggerFiles"

	"github.com/gin-gonic/gin"
)

然后注册一下swagger api的路由(因为我们需要访问swagger的页面,它本质上也只是一个页面而已)

然后我们就需要注册一下swagger api相关路由了

go">r.GET("/swagger/*any", gs.WrapHandler(swaggerFiles.Handler))

这个时候,我们把项目运行起来,在访问http://localhost:8080/swagger/index.html就能看到Swagger2.0 Api文档了。

小结

我觉得Q1mi(李文周)的教程算是一种提纲式的,略一遍的教程,但是并不很详细,只是入门起来够用,是那种20分钟就能看完的教程。

而且它很精简,精简到我做笔记只是把它的内容复制过来,相当于让自己有个印象而已。

goSwaggo_125">go中文文档中的Swaggo

介绍

很多人不喜欢写api文档,不仅浪费大量的时间,而且无法保证面面俱到,但是api文档还是要有的,那么有没有一款工具能够根据我们的代码自动生成api文档呢? 让我们能够只专注于代码呢? 那就是swagger。

最后要呈现的文档效果大概如下:

swag<a class=go" />

使用

  1. 要使用swaggo,首先需要安装swag cli
go">go get -u github.com/swaggo/swag/cmd/swag
  1. 出来swag cli之外,我们还需要两个包
go"># gin-swagger 中间件
go get github.com/swaggo/gin-swagger
# swagger 内置文件
go get github.com/swaggo/gin-swagger/swaggerFiles
  1. 找到我们的入口函数(main函数)

首先需要import我们刚才安装的两个包,在原有import内,添加如下信息

go">import (
    ginSwagger "github.com/swaggo/gin-swagger"
    "github.com/swaggo/gin-swagger/swaggerFiles"
)

全局配置各项参数的作用

然后main函数注释如下,另外需要在注册路由的地方,为swagger注册一下路由。

下面的注释中:

titile:文档标题

version:版本 (会在页面标题的右上角展示)

description,termsOfService,contact,info,license: 这些都是一些注解,用来对swagger-ui界面上的一些信息进行描述,区别在于。

Info注解是对swagger-ui界面上的基本信息进行描述,比如界面的标题,界面的介绍等。

Contact注解是对swagger-ui界面上一些和接口有关的联系人的信息进行描述,包括但不限于开发人员名称,地址等。

License注解是对swagger-ui界面上的一些和接口有关的服务条款或者使用的开源协议进行描述,包括服务名称,服务所在地址。

description属性就是对界面做一个简单扼要的介绍,即用来描述界面是用来干什么的或者一些其他的注意事项等。

termsOfService属性配置的是服务网站

host,BasePath:如果你想直接swagger调试api,这两项需要填写正确,前者为服务文档的端口,ip,后者为基础路径,也就是你接口地址的前缀地址。

go">// @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 me@razeen.me

// @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()
    // 为swagger注册路由
    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")
}
  1. 如果注释写的没有问题,在main.go同目录下执行swag init

此时会自动生成文档,会发现在同目录下多出了一个docs文件夹,此时我们再引入这个文件夹,如下,然后就可以运行我们的项目,进入到swagger-ui里了。

image-20210916230320993

此时会看到一个只有我们刚才写的配置信息的页面,其它的都没有。

swag<a class=go" />

  1. 为每个路由处理函数都加上注释

刚才我们只是在main函数上加了一下注释,相当于是配置了一下swagger的全局信息,而我们在项目中会写很多的接口,这每一个接口,也都需要一定的配置。

go">// @Summary 测试SayHello
// @Description 向你说Hello
// @Tags 测试
// @Accept json
// @Produce application/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<a class=go" />

swag<a class=go" />

各个接口的注释参数作用

Tags

用来给API分组

Accept

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

Produce

返回的数据结构,一般都是使用json,其它支持如下:

Mime Type声明
application/jsonjson
text/xmlxml
text/plainplain
htmlhtml
multipart/form-datampfd
application/x-www-form-urlencodedx-www-form-urlencoded
application/vnd.api+jsonjson-api
application/x-json-streamjson-stream
application/octet-streamoctet-stream
image/pngpng
image/jpegjpeg
image/gifgif
Param

一般如下:

go">// 由参数名 参数类型 参数数据类型 是否必须 参数描述 其它属性构成
// @Param who query string true "人名"
参数类型

参数类型主要有三种:

  • path:该类型的参数之间拼接在URL中

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

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

go">// @Param user formData string true "用户名" default(admin)

path和query的区别在于:

query:user/john?password=*****

path:user/{username}

在query中,取出参数一般是键值对的形式存储,而path只是一个路径的拼接

参数数据类型

主要支持以下几种:

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

如果是上传文件的话,用file类型,参数类型选择formData

是否是必须

声明该参数是否是必须需要的,必填的,值为true、false

参数描述

可以对此参数作一些说明

其他属性

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

go">枚举
// @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

成功响应的数据。格式如下:

go">// @Success 1.Http响应码 {2.响应参数类型} 3.响应数据类型 4.其他描述
  • Http响应码:

    例如200,400,500那些

  • 响应参数类型/响应数据类型:

可以是自定义类型,也可以是Json类型,通常来讲我们都会使用自定义类型,返回一些我们指定的Json数据。

go">// @Success 200 {object} main.testStruct

可以在models文件夹中创建一个文件来存储所有的swagger返回json结构体

image-20210917112231770

在注释上通过包名.struct的方式即可找到,如果要返回struct数组,可以这样写:

go">// @Success 200 {anrry} main.File

如果返回的是json数据可以如下写:

go">// @Success 200 {string} json ""

然后可以在后面加一些对本结果的说明

Router

指定路由和HTTP方法,格式为:

go">// @Router /path/to/handle [HTTP方法]

不需要加basePath(基础路径)

生成文档与测试

当我们的配置写完之后,在main.go下运行swag init即可生成和更新文档,点击swagger-ui中的Try it out即可测试,如果部分的API需要登录之后才能测试,可以Try登录接口即可。

优化

在上面的操作进行过之后,已经可以使用了,但文档一般只是我们测试的时候需要,当我们的产品上线之后,就不需要让用户看到了,而且swaggo是之间build到二进制文件中的,带swaggo的包也会大很多。

解决方案就是在编译的时候通过build tag来控制是否编译文档。

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

go">package main

//...

var swagHandler gin.HandlerFunc

func main(){
    // ...

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

    //...
}

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

go">// +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来打包不带文档的包。

可以看到大小的差距。

image-20210917153751610

如果使用了Token

如果我们在程序中使用了token中间键,只需要添加下面的注释即可:

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

gogit_hub_487">swag-go说明文档(git hub)

快速开始

  • 下载swag
go">$ go get -u github.com/swaggo/swag/cmd/swag

# 1.16 及以上版本
$ go install github.com/swaggo/swag/cmd/swag@latest
  • 在包含main.go文件的项目根目录运行swag init,这会解析注释并生成需要的文件(docs文件夹和docs/docs.go文件夹)
go">swag init

如果通用api注释没有写在main.go文件中,也可以使用-g标识符来告诉swag

go">swag init -g http/api.go

支持的框架

  • gin
  • echo
  • buffalo
  • net/http

声明式注释格式

goAPI_521">main.go上通用API信息

注释说明示例
title必填 应用程序的名称。// @title Swagger Example API
version必填 提供应用程序API的版本。// @version 1.0
description应用程序的简短描述。// @description This is a sample server celler server.
tag.name标签的名称。// @tag.name This is the name of the tag
tag.description标签的描述。// @tag.description Cool Description
tag.docs.url标签的外部文档的URL。// @tag.docs.url https://example.com
tag.docs.description标签的外部文档说明。// @tag.docs.description Best example documentation
termsOfServiceAPI的服务条款。// @termsOfService http://swagger.io/terms/
contact.name公开的API的联系信息。// @contact.name API Support
contact.url联系信息的URL。 必须采用网址格式。// @contact.url http://www.swagger.io/support
contact.email联系人/组织的电子邮件地址。 必须采用电子邮件地址的格式。// @contact.email support@swagger.io
license.name必填 用于API的许可证名称。// @license.name Apache 2.0
license.url用于API的许可证的URL。 必须采用网址格式。// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
host运行API的主机(主机名或IP地址)。// @host localhost:8080
BasePath运行API的基本路径。// @BasePath /api/v1
query.collection.format请求URI query里数组参数的默认格式:csv,multi,pipes,tsv,ssv。 如果未设置,则默认为csv。// @query.collection.format multi
schemes用空格分隔的请求的传输协议。// @schemes http https
x-name扩展的键必须以x-开头,并且只能使用json值// @x-example-key {“key”: “value”}

使用markdown描述

如果文档中的短字符串不足以完整表达,或者需要展示图片,代码示例等类似的内容,则可能需要使用Markdown描述。要使用Markdown描述,请使用一下注释。

注释说明示例
title必填 应用程序的名称。// @title Swagger Example API
version必填 提供应用程序API的版本。// @version 1.0
description.markdown应用程序的简短描述。 从api.md文件中解析。 这是@description的替代用法。// @description.markdown No value needed, this parses the description from api.md
tag.name标签的名称。// @tag.name This is the name of the tag
tag.description.markdown标签说明,这是tag.description的替代用法。 该描述将从名为tagname.md的文件中读取。// @tag.description.markdown

API注释

注释描述
description操作行为的详细说明。
description.markdown应用程序的简短描述。该描述将从名为endpointname.md的文件中读取。
id用于标识操作的唯一字符串。在所有API操作中必须唯一。
tags每个API操作的标签列表,以逗号分隔。
summary该操作的简短摘要。
acceptAPI可以使用的MIME类型的列表。值必须如“Mime类型”中所述。
produceAPI可以生成的MIME类型的列表。值必须如“Mime类型”中所述。
param用空格分隔的参数。param name,param type,data type,is mandatory?,comment attribute(optional)
security每个API操作的安全性。
success以空格分隔的成功响应。return code,{param type},data type,comment
failure以空格分隔的故障响应。return code,{param type},data type,comment
response与success、failure作用相同
header以空格分隔的头字段。 return code,{param type},data type,comment
router以空格分隔的路径定义。 path,[httpMethod]
x-name扩展字段必须以x-开头,并且只能使用json值。

Mime类型

swag 接受所有格式正确的MIME类型, 即使匹配 */*。除此之外,swag还接受某些MIME类型的别名,如下所示:

AliasMIME Type
jsonapplication/json
xmltext/xml
plaintext/plain
htmltext/html
mpfdmultipart/form-data
x-www-form-urlencodedapplication/x-www-form-urlencoded
json-apiapplication/vnd.api+json
json-streamapplication/x-json-stream
octet-streamapplication/octet-stream
pngimage/png
jpegimage/jpeg
gifimage/gif

参数类型

  • query
  • path
  • header
  • body
  • formData

数据类型

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

安全性

注释描述参数示例
securitydefinitions.basicBasic auth.// @securityDefinitions.basic BasicAuth
securitydefinitions.apikeyAPI key auth.in, name// @securityDefinitions.apikey ApiKeyAuth
securitydefinitions.oauth2.applicationOAuth2 application auth.tokenUrl, scope// @securitydefinitions.oauth2.application OAuth2Application
securitydefinitions.oauth2.implicitOAuth2 implicit auth.authorizationUrl, scope// @securitydefinitions.oauth2.implicit OAuth2Implicit
securitydefinitions.oauth2.passwordOAuth2 password auth.tokenUrl, scope// @securitydefinitions.oauth2.password OAuth2Password
securitydefinitions.oauth2.accessCodeOAuth2 access code auth.tokenUrl, authorizationUrl, scope// @securitydefinitions.oauth2.accessCode OAuth2AccessCode
参数注释示例
in// @in header
name// @name Authorization
tokenUrl// @tokenUrl https://example.com/oauth/token
authorizationurl// @authorizationurl https://example.com/oauth/authorize
scope.hoge// @scope.write Grants write access

小结

之后看了看,感觉这个东西就是跟一个字典一样,既然如此我都复制粘贴过来也没什么意义。

链接如下,大家自己看吧。

参考资料

  • 狂神说视频

  • 李文周博客

  • Go中文文档

  • swag-go官方文档


http://www.niftyadmin.cn/n/1736538.html

相关文章

日志异常处理errors学习笔记

与你相识 博主介绍&#xff1a; – 本人是普通大学生一枚&#xff0c;每天钻研计算机技能&#xff0c;CSDN主要分享一些技术内容&#xff0c;因我常常去寻找资料&#xff0c;不经常能找到合适的&#xff0c;精品的&#xff0c;全面的内容&#xff0c;导致我花费了大量的时间&a…

elasticsearch V1.0

与你相识 博主介绍&#xff1a; – 本人是普通大学生一枚&#xff0c;每天钻研计算机技能&#xff0c;CSDN主要分享一些技术内容&#xff0c;因我常常去寻找资料&#xff0c;不经常能找到合适的&#xff0c;精品的&#xff0c;全面的内容&#xff0c;导致我花费了大量的时间&a…

Go单元测试学习笔记 V1.0

与你相识 博主介绍&#xff1a; – 本人是普通大学生一枚&#xff0c;每天钻研计算机技能&#xff0c;CSDN主要分享一些技术内容&#xff0c;因我常常去寻找资料&#xff0c;不经常能找到合适的&#xff0c;精品的&#xff0c;全面的内容&#xff0c;导致我花费了大量的时间&a…

Xorm学习笔记

与你相识 博主介绍&#xff1a; – 本人是普通大学生一枚&#xff0c;每天钻研计算机技能&#xff0c;CSDN主要分享一些技术内容&#xff0c;因我常常去寻找资料&#xff0c;不经常能找到合适的&#xff0c;精品的&#xff0c;全面的内容&#xff0c;导致我花费了大量的时间&a…

casbin学习笔记

与你相识 博主介绍&#xff1a; – 本人是普通大学生一枚&#xff0c;每天钻研计算机技能&#xff0c;CSDN主要分享一些技术内容&#xff0c;因我常常去寻找资料&#xff0c;不经常能找到合适的&#xff0c;精品的&#xff0c;全面的内容&#xff0c;导致我花费了大量的时间&a…

python module ‘mitmproxy.proxy‘ has no attribute ‘config‘问题解决

python module ‘mitmproxy.proxy’ has no attribute config’问题解决 原因是mitmproxy的版本太高&#xff0c;目前7.x的版本已经不是这样解决了&#xff0c;使用下面的语句降一下版本即可&#xff1a; pip install mitmproxy6.0.2 -i http://pypi.douban.com/simple/

001问 | 为什么Go语言的for循环结构体不能用var?

偶然间&#xff0c;我的好朋友问起我这个问题&#xff0c;我还真没有好好思考过这个问题。 我查了Go语言圣经&#xff0c;知名博客&#xff0c;以及Go中文文档&#xff0c;发现都没有阐述这个问题。 后来找来找去也只有下面的解释&#xff1a; for的初始化语句不能是任何类型…

002问 | 在Go语言中fmt.Println和println的区别?

它们的区别是什么&#xff1f; 我还真没思考过这个问题。 可以看到它们的颜色不同&#xff0c;fmt.Println输出到标准输出&#xff0c;而println输出到标准错误。log标准包里的打印函数会默认写入标准错误。println主要程序启动和调试的时候用&#xff0c;应该是Go语言内部的实…