Swagger是很流行的API文档和API 调试工具,只要定义好 API 文档,API 调试、可直接使用,无需再次定义。API 文档和 API 开发调试使用同一个工具,API 调试完成后即可保证和 API 文档定义完全一致。高效、及时、准确!
下面演示怎么简单快速在Golang项目中引入Swagger功能。
1、首先安装Swagger安装包
go get -u github.com/swaggo/swag/cmd/swag
2、下载项目框架中调用的gin-swagger包
go get -u github.com/swaggo/gin-swagger
go get -u github.com/swaggo/files
3、项目中引用 gin-swagger包
如下面所示:
import "github.com/swaggo/gin-swagger" // gin-swagger middleware
import "github.com/swaggo/files" // swagger embed files
package routers
import (
"fmt"
"time"
"stockapp/src/services"
"stockapp/src/utils"
docs "stockapp/docs"
"github.com/gin-gonic/gin"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
swaggerfiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
)
func Router() *gin.Engine {
prometheus.MustRegister(utils.GinRequests)
r := gin.New()
r.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
// Define Custom Format
return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
param.ClientIP,
param.TimeStamp.Format(time.RFC1123),
param.Method,
param.Path,
param.Request.Proto,
param.StatusCode,
param.Latency,
param.Request.UserAgent(),
param.ErrorMessage,
)
}))
r.Use(func(c *gin.Context) {
utils.GinRequests.Inc()
})
r.Use(gin.Recovery())
// r.LoadHTMLGlob("templates/*")
// r.LoadHTMLFiles("templates/template1.html", "templates/template2.html")
docs.SwaggerInfo.BasePath = ""
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))
r.GET("/metrics", gin.WrapH(promhttp.Handler()))
r.GET("/", services.GetIndex)
r.GET("/user/getUserList", services.GetUserList)
r.POST("/user/:name", services.CreateUser)
r.DELETE("/user/:name", services.DeleteUser)
r.POST("/login", services.Login)
return r
}
4、进行swagger初始化,生成docs目录,并生成swagger.json 和swagger.yaml配置文件。
swag init
5、在项目服务中加入swagger注释说明信息
package services
import (
"fmt"
"log"
"stockapp/src/dao"
"stockapp/src/models"
"stockapp/src/utils""math/rand"
"github.com/gin-gonic/gin"
)// GetUserList
// @Summary 所有用户
// @Tags 用户模块
// @Success 200 {string} json{"code", "message"}
// @Router /user/getUserList [get]
func GetUserList(c *gin.Context) {
utils.GinRequests.Inc()
data := make([]*models.UserBasic, 0)
var err errorfunc() {
defer func() {
if err := recover(); err != nil {
log.Printf("Panic in GetUserList: %v", err)
c.JSON(500, gin.H{"error": "Internal server error"})
}
}()
data, err = dao.GetUserList()
if err != nil {
log.Println("userservice Error from Dao:", err.Error())
c.JSON(500, gin.H{
"message": err.Error(),
})
}
for _, v := range data {
log.Println("userservice get data from Dao:", v)}
c.JSON(200, gin.H{
"message": data,
})
}()
}// CreateUser
// @Summary 新增用户
// @Tags 用户模块
// @param name query string false "用户名"
// @param password query string false "密码"
// @param rePassword query string false "确认密码"
// @Success 200 {string} json{"code", "message"}
// @Router /user/createUser [POST]
func CreateUser(c *gin.Context) {
utils.GinRequests.Inc()
user := models.UserBasic{}
user.Name = c.Query("name")
password := c.Query("password")
rePassword := c.Query("rePassword")salt := fmt.Sprintf("%06d", rand.Int31())
user.Salt = saltdata := dao.FindUserByName(user.Name)
if data.Name != "" {
c.JSON(-1, gin.H{
"code": -1,
"message": "用户名已经注册",
"data": user,
})
return
}if password != rePassword {
c.JSON(-1, gin.H{
"code": -1,
"message": "两次密码不一致",
"data": user,
})
return
}user.Password = utils.MakePassword(password, salt)
dao.CreateUser(&user)
c.JSON(200, gin.H{
"code": 0,
"message": "新增用户成功",
"data": user,
})
}func FindUserByNameAndPwd(c *gin.Context) {
}
func FindUserByPhone(c *gin.Context) {
}
func FindUserByEmail(c *gin.Context) {
}
// DeleteUser
// @Summary 删除用户
// @Tags 用户模块
// @param name query string false "用户名"
// @Success 200 {string} json{"code", "message"}
// @Router /user/DeleteUser [DELETE]
func DeleteUser(c *gin.Context) {
utils.GinRequests.Inc()
user := models.UserBasic{}data := dao.FindUserByName(user.Name)
if data.Name == "" {
c.JSON(-1, gin.H{
"code": -1,
"message": "用户名存在!",
"data": user,
})
return
}
dao.DeleteUser(&user)
c.JSON(200, gin.H{
"code": 0,
"message": "删除用户成功",
"data": user,
})
}
6、再次更新swagger配置信息
swag init
7、启动项目程序
go run main.go
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /swagger/*any --> github.com/swaggo/gin-swagger.CustomWrapHandler.func1 (4 handlers)
[GIN-debug] GET /metrics --> github.com/gin-gonic/gin.WrapH.func1 (4 handlers)
[GIN-debug] GET / --> stockapp/src/services.GetIndex (4 handlers)
[GIN-debug] GET /user/getUserList --> stockapp/src/services.GetUserList (4 handlers)
[GIN-debug] POST /user/:name --> stockapp/src/services.CreateUser (4 handlers)
[GIN-debug] DELETE /user/:name --> stockapp/src/services.DeleteUser (4 handlers)
[GIN-debug] POST /login --> stockapp/src/services.Login (4 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :8081
127.0.0.1 - [Fri, 02 Jun 2023 09:55:31 CST] "GET /swagger/index.html HTTP/1.1 200 428.181µs "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/113.0" "
127.0.0.1 - [Fri, 02 Jun 2023 09:55:31 CST] "GET /swagger/swagger-ui-bundle.js HTTP/1.1 200 2.041091ms "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/113.0" "
127.0.0.1 - [Fri, 02 Jun 2023 09:55:31 CST] "GET /swagger/swagger-ui.css HTTP/1.1 200 2.356918ms "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/113.0" "
127.0.0.1 - [Fri, 02 Jun 2023 09:55:31 CST] "GET /swagger/swagger-ui-standalone-preset.js HTTP/1.1 200 2.840201ms "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/113.0" "
127.0.0.1 - [Fri, 02 Jun 2023 09:55:32 CST] "GET /swagger/favicon-16x16.png HTTP/1.1 200 58.431µs "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/113.0" "
127.0.0.1 - [Fri, 02 Jun 2023 09:55:32 CST] "GET /swagger/doc.json HTTP/1.1 200 259.115µs "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/113.0" "
2023/06/02 09:56:01 /Users/baineng/Documents/devops/golang/stockapp/src/dao/userbasic.go:28 record not found
[657.026ms] [rows:0] SELECT * FROM `user_basic` WHERE name = '' AND `user_basic`.`deleted_at` IS NULL ORDER BY `user_basic`.`id` LIMIT 1
127.0.0.1 - [Fri, 02 Jun 2023 09:56:01 CST] "DELETE /user/DeleteUser?name=baineng HTTP/1.1 200 657.351805ms "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/113.0" "
现在您已经具备swagger API文档与测试功能啦。
8、swagger API功能测试
在浏览器中输入: http://127.0.0.1:8081/swagger/index.html,您看到下面类似信息。
1)测试创建一个新用户
2)测试删除一个用户
总结:Swagger是一组开源项目,支持多种框:如Gin, Java sprintboot架构,可帮助我们快速构建标准的API文档及API测试,交付提高效率!
-
Swagger-tools:提供各种与Swagger进行集成和交互的工具。
-
Swagger-core: 用于Java/Scala的的Swagger实现。与JAX-RS(Jersey、Resteasy、CXF...)、Servlets和Play框架进行集成。
-
Swagger-js: 用于JavaScript的Swagger实现。
-
Swagger-node-express: Swagger模块,用于node.js的Express web应用框架。
-
Swagger-ui:一个无依赖的HTML、JS和CSS集合,可以为Swagger兼容API动态生成优雅文档。
-
Swagger-codegen:一个模板驱动引擎,通过分析用户Swagger资源声明以各种语言生成客户端代码。