Swagger
This chapter will introduce how to generate Swagger documentation.
Introduction
API documentation is an essential component in project development. As a well-known open-source documentation generation tool, Swagger uses the Swag command-line tool in the Go ecosystem to generate documentation files by parsing code comments. Understanding commenting techniques can help you write easy-to-understand API documentation. When Go-Sail starts, it will determine whether to enable Swagger documentation based on the configuration file. The documentation generation process needs to be handled by developers themselves. Below, we'll provide some simple examples to help you get started quickly.
Preparation
First, you should install the following dependencies:
Swag
go get -u github.com/swaggo/swag/cmd/[email protected]
Node
Redocly
npm i -g @redocly/[email protected]
Code Comments
VO
package request
import (
"fmt"
"github.com/keepchen/go-sail/v3/constants"
)
// GetUserInfoReqVo Request parameters for getting user information
// swagger: model
type GetUserInfoReqVo struct {
UserID int64 `json:"userId" form:"userId" validate:"required"` // 用户id
}
func (v GetUserInfoReqVo) Validator() (constants.ICodeType, error) {
if v.UserID < 1 {
return constants.ErrRequestParamsInvalid, fmt.Errorf("field [userId], value:{%d} is invalid", v.UserID)
}
return constants.ErrNone, nil
}
package response
import (
modelsEnum "github.com/keepchen/go-sail/v3/examples/pkg/common/enum/models"
"github.com/keepchen/go-sail/v3/http/pojo/dto"
)
// GetUserInfoAckVo Response structure for getting user information
// swagger: model
type GetUserInfoAckVo struct {
dto.Base
// Response body
// in: body
// required: true
Data struct {
User UserInfo `json:"user"`
Wallet WalletInfo `json:"wallet"`
} `json:"data" format:"object"`
}
// UserInfo Basic user information data structure
// swagger: model
type UserInfo struct {
UserID int64 `json:"userId" validate:"required"` // User ID
// User nickname
// in: body
// required: true
Nickname string `json:"userInfo" validate:"required"`
// Account status
//
// UserStatusCodeNormal = UserStatusCode(0) //normal
// UserStatusCodeForbidden = UserStatusCode(1) //forbidden
//
// in: body
// required: true
Status modelsEnum.UserStatusCode `json:"status" enums:"0,1" validate:"required"`
}
// WalletInfo Wallet information data structure
// swagger: model
type GetUserInfoAckVo struct {
// Account balance
// in: body
// required: true
Amount float64 `json:"amount" validate:"required"`
// Wallet status
//
// WalletStatusCodeNormal = WalletStatusCode(0) //normal
// WalletStatusCodeForbidden = WalletStatusCode(1) //forbidden
//
// in: body
// required: true
Status modelsEnum.WalletStatusCode `json:"status" enums:"0,1" validate:"required"`
}
func (v GetUserInfoAckVo) GetData() interface{} {
return v.Data
}
var _ dto.IResponse = &GetUserInfoAckVo{}
Routes
package routes
import (
"net/http"
"github.com/gin-contrib/gzip"
"github.com/keepchen/go-sail/v3/examples/pkg/app/user/http/middleware"
"github.com/gin-gonic/gin"
"github.com/keepchen/go-sail/v3/examples/pkg/app/user/http/handler"
)
// RegisterRoutes register routes
func RegisterRoutes(r *gin.Engine) {
//k8s健康检查接口
r.GET("/actuator/health", func(c *gin.Context) {
c.String(http.StatusOK, "%s", "ok")
})
apiGroup := r.Group("/api/v1")
{
apiGroup.GET("/say-hello", handler.SayHello)
userGroup := apiGroup.Group("/user")
{
userGroup.Use(middleware.AuthCheck()).GET("/info", handler.GetUserInfo)
}
}
}
Handler Functions
package handler
import (
"github.com/gin-gonic/gin"
"github.com/keepchen/go-sail/v3/examples/pkg/app/user/service"
)
// GetUserInfo Get user information
// @Tags user / User Related
// @Summary user/info - Get user information
// @Description Get user information
// @Security ApiKeyAuth
// @Accept application/json
// @Produce json
// @Param parameter query request.GetUserInfoReqVo true "Query parameters"
// @Success 200 {object} response.GetUserInfoAckVo
// @Failure 400 {object} dto.Error400
// @Failure 500 {object} dto.Error500
// @Router /user/info [get]
func GetUserInfo(c *gin.Context) {
service.GetUserInfoSvc(c)
}
Service Functions
package service
import (
"fmt"
"github.com/keepchen/go-sail/v3/sail"
"github.com/gin-gonic/gin"
"github.com/keepchen/go-sail/v3/constants"
"github.com/keepchen/go-sail/v3/examples/pkg/app/user/http/vo/request"
"github.com/keepchen/go-sail/v3/examples/pkg/app/user/http/vo/response"
)
func SayHelloSvc(c *gin.Context) {
var (
form request.SayHelloReqVo
resp response.SayHelloAckVo
)
if err := c.ShouldBind(&form); err != nil {
sail.Response(c).Wrap(constants.ErrRequestParamsInvalid, resp).Send()
return
}
if errorCode, err := form.Validator(); err != nil {
sail.Response(c).Wrap(errorCode, resp, err.Error()).Send()
return
}
var nickname string
if len(form.Nickname) == 0 {
nickname = "go-sail"
} else {
nickname = form.Nickname
}
resp.Data = fmt.Sprintf("hello, %s", nickname)
sail.Response(c).Wrap(constants.ErrNone, resp).Send()
//sail.Response(c).Data(resp.Data)
}
Generate Command
swag init --dir pkg/app/user \
--output pkg/app/user/http/docs \
--parseDependency --parseInternal \
--generalInfo user.go && \
redoc-cli bundle pkg/app/user/http/docs/*.yaml -o pkg/app/user/http/docs/docs.html
After modifying the response path as needed, execute the generate command to generate the documentation content. The above code example can be found in the source files at: github.com/keepchen/go-sail.
Plugins
Redocly Copy Button
In the documentation pages generated by the Redocly tool, there is no button to quickly copy API routes, so we provide a plugin that can inject copy buttons into the generated HTML files.
You can use it like this:
node plugins/redocly/redocly-copy.js pkg/app/user/http/docs/*.html
The source code for this tool can be found here: github.com/keepchen/go-sail.
Makefile
You can integrate the above commands into a Makefile to greatly improve efficiency.
# swag version >= 1.16.4
# go get -u github.com/swaggo/swag/cmd/[email protected]
gen-swag-user:
@echo "+ $@"
@$(if $(SWAG), , \
$(error Please install swag cli, using go: "go get -u github.com/swaggo/swag/cmd/[email protected]"))
@$(if $(REDOCCLI), , \
$(error Please install redoc cli, using npm or yarn: "npm i -g @redocly/[email protected]"))
swag init --dir pkg/app/user \
--output pkg/app/user/http/docs \
--parseDependency --parseInternal \
--generalInfo user.go && \
redoc-cli bundle pkg/app/user/http/docs/*.yaml -o pkg/app/user/http/docs/docs.html && \
node plugins/redocly/redocly-copy.js pkg/app/user/http/docs/*.html
You can find a more complete example here.