swag
swaggo/swag ist eine Implementierung von Swagger API 2.0 in Go. Durch das Schreiben von Kommentaren in einem bestimmten Format können API-Dokumentationen im swagger.json- und swagger.yaml-Format generiert werden, die einfach exportiert und importiert werden können.
Repository: swaggo/swag: Automatically generate RESTful API documentation with Swagger 2.0 for Go. (github.com)
Dokumentation: swaggo/swag: Automatically generate RESTful API documentation with Swagger 2.0 for Go. (github.com)
Swag unterstützt standardmäßig folgende Web-Frameworks. In diesem Artikel wird gin als Beispiel verwendet, um zu demonstrieren, wie gin in Kombination mit swagger schnell API-Dokumentationen generiert.
TIP
Wenn Sie mit der Swagger-Syntax nicht vertraut sind, besuchen Sie About Swagger Specification | Documentation | Swagger
Installation
Laden Sie zuerst das Swagger-Kommandozeilen-Tool herunter
go install github.com/swaggo/swag/cmd/swag@latestLaden Sie dann die Swagger-Quellcode-Abhängigkeit herunter
go get github.com/swaggo/swagTIP
Um Probleme zu vermeiden, müssen beide Versionen übereinstimmen.
Laden Sie dann die statische Dateibibliothek von Swagger herunter. HTML, CSS, JS usw. wurden in Go-Code eingebettet.
go get github.com/swaggo/files@latestLaden Sie schließlich die Gin-Adapterbibliothek von Swagger herunter
go get github.com/swaggo/gin-swagger@latestDa dieser Artikel nur gin als Beispiel verwendet, informieren Sie sich bitte selbst über Adapter für andere Web-Frameworks. Sie sind im Grunde alle sehr ähnlich.
Verwendung
Erstellen Sie mit go mod ein grundlegendes Go-Projekt, erstellen Sie main.go und schreiben Sie folgenden Inhalt.
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
// @title Swagger Example API
// @version 1.0
// @description This is a sample server celler server.
// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io
// @BasePath /api/v1
func main() {
engine := gin.Default()
engine.GET("/api/v1/ping", Ping)
engine.Run(":80")
}
// Ping godoc
// @Summary say hello world
// @Description return hello world json format content
// @param name query string true "name"
// @Tags system
// @Produce json
// @Router /ping [get]
func Ping(ctx *gin.Context) {
ctx.JSON(200, gin.H{
"message": fmt.Sprintf("Hello World!%s", ctx.Query("name")),
})
}Dies ist ein sehr einfaches gin-Web-Beispiel. Die Kommentare über der main-Funktion sind die grundlegenden Informationen des Dokuments, und die Ping-Funktion ist eine normale Schnittstelle. Führen Sie als Nächstes den Befehl aus, um die Dokumentation zu generieren. Standardmäßig wird sie im docs-Verzeichnis auf derselben Ebene wie main.go erstellt.
swag initÄndern Sie den Code in main.go
package main
import (
"fmt"
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
// Anonymer Import des generierten API-Dokumentations-Pakets
_ "golearn/docs"
)
// @title Swagger Example API
// @version 1.0
// @description This is a sample server celler server.
// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io
// @BasePath /api/v1
func main() {
engine := gin.Default()
// Swagger statische Datei-Route registrieren
engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
engine.GET("/api/v1/ping", Ping)
engine.Run(":80")
}
// Ping godoc
// @Summary say hello world
// @Description return hello world json format content
// @param name query string true "name"
// @Tags system
// @Produce json
// @Router /ping [get]
func Ping(ctx *gin.Context) {
ctx.JSON(200, gin.H{
"message": fmt.Sprintf("Hello World!%s", ctx.Query("name")),
})
}Führen Sie das Programm aus und rufen Sie 127.0.0.1/swagger/index.html auf. Die Oberfläche sieht wie folgt aus:

Damit wurde eine grundlegende API-Dokumentation gestartet. Abgesehen von einigen besonders zu beachtenden Punkten gibt es keinen großen Unterschied zur Verwendung in anderen Sprachen.
Parameter
Das Format zur Definition von Parametern ist:
@param name paramtype datatype isRequired commentEin Beispiel:
@param userId query int true "user unique id"Die unterstützten Parametertypen sind:
- query
- path
- header
- body
- formData
Die Datentypen sind:
- string (string)
- integer (int, uint, uint32, uint64)
- number (float32)
- boolean (bool)
- user defined struct
Der Parametertyp kann auch Ihr eigener Typ sein, vorausgesetzt, er kann von Swagger gescannt werden.
Antwort
Das grundlegende Format zur Definition von Schnittstellenantworten:
// @Success 200 {array} model.Account
// @Failure 400 {object} httputil.HTTPError
// @Failure 404 {object} httputil.HTTPError
// @Failure 500 {object} httputil.HTTPErrorBestehend aus Statuscode, Basistyp und Datentyp. {array} bedeutet, dass es sich um ein Array handelt, und zeigt die Array-Form des Datentyps. {object} zeigt die ursprüngliche Form des Datentyps. Zum Beispiel definieren wir normalerweise einen einheitlichen Antwortkörper:
type JSONResult struct {
Code int `json:"code" `
Message string `json:"message"`
Data interface{} `json:"data"`
}Der Typ des Data-Feldes ist unbestimmt. Bei der Beschreibung von Antwortbeispielen kann er wie folgt kombiniert werden:
// Kombination
@success 200 {object} jsonresult.JSONResult{data=Account} "desc"
// Array
@success 200 {object} jsonresult.JSONResult{data=[]Account} "desc"Modelle
Kommentare zu Strukturfeldern werden von Swagger als Modellfeldkommentare gescannt:
package model
type Account struct {
// account id
ID int `json:"id" example:"1"`
// username
Name string `json:"name" example:"account name"`
}Der Wert des example-Tags wird als Beispielwert auf der Seite angezeigt. Natürlich werden auch Feldbeschränkungen unterstützt:
type Foo struct {
Bar string `minLength:"4" maxLength:"16"`
Baz int `minimum:"10" maximum:"20" default:"15"`
Qux []string `enums:"foo,bar,baz"`
}Alle Modelle müssen bei der Verwendung sicherstellen, dass sie von Swagger gescannt werden können, sonst funktionieren sie nicht.
Authentifizierung
Im Bereich der Authentifizierung werden unterstützt:
- Basic Auth
- API Key
- OAuth2 app auth
- OAuth2 implicit auth
- OAuth2 password auth
- OAuth2 access code auth
Wenn die Schnittstellenauthentifizierung JWT verwendet und im Authorization-Feld des Headers gespeichert wird, können wir wie folgt definieren:
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
Im Wesentlichen ist dies nur ein API-Key. Wenn Sie ein Bearer-Token übergeben, müssen Sie das Bearer-Präfix manuell hinzufügen.

Fügen Sie dann den folgenden Kommentar zu den Schnittstellen hinzu, die Authentifizierung erfordern:
// @security BearerDer Wert ist der Name, den Sie in securityDefinitions definiert haben.
Konfiguration
Swag speichert tatsächlich mehrere verschiedene Swagger-Instanzen in einer Map. ginSwagger dient als Adapter, um doc.json aus den Instanzen zu lesen, also die API-Schnittstellendefinitionsdatei. swaggerFiles stellt statische HTML-Dateien für die Anzeige der Webseite bereit, parst die API-Definition und generiert die Oberfläche. Wenn Sie den gesamten Prozess verstehen, können Sie benutzerdefinierte Operationen durchführen.
// Name is a unique name be used to register swag instance.
// Standardinstanzname
const Name = "swagger"
var (
swaggerMu sync.RWMutex
// Instanztabelle
swags map[string]Swagger
)func CustomWrapHandler(config *Config, handler *webdav.Handler) gin.HandlerFunc {
var once sync.Once
if config.InstanceName == "" {
config.InstanceName = swag.Name
}
if config.Title == "" {
config.Title = "Swagger UI"
}
// create a template with name
index, _ := template.New("swagger_index.html").Parse(swaggerIndexTpl)
var matcher = regexp.MustCompile(`(.*)(index\.html|doc\.json|favicon-16x16\.png|favicon-32x32\.png|/oauth2-redirect\.html|swagger-ui\.css|swagger-ui\.css\.map|swagger-ui\.js|swagger-ui\.js\.map|swagger-ui-bundle\.js|swagger-ui-bundle\.js\.map|swagger-ui-standalone-preset\.js|swagger-ui-standalone-preset\.js\.map)[?|.]*`)
return func(ctx *gin.Context) {
if ctx.Request.Method != http.MethodGet {
ctx.AbortWithStatus(http.StatusMethodNotAllowed)
return
}
// Routenabgleich
matches := matcher.FindStringSubmatch(ctx.Request.RequestURI)
if len(matches) != 3 {
ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound))
return
}
path := matches[2]
once.Do(func() {
handler.Prefix = matches[1]
})
switch filepath.Ext(path) {
case ".html":
ctx.Header("Content-Type", "text/html; charset=utf-8")
case ".css":
ctx.Header("Content-Type", "text/css; charset=utf-8")
case ".js":
ctx.Header("Content-Type", "application/javascript")
case ".png":
ctx.Header("Content-Type", "image/png")
case ".json":
ctx.Header("Content-Type", "application/json; charset=utf-8")
}
switch path {
// Hauptseite
case "index.html":
_ = index.Execute(ctx.Writer, config.toSwaggerConfig())
// API-Beschreibungsdatei
case "doc.json":
doc, err := swag.ReadDoc(config.InstanceName)
if err != nil {
ctx.AbortWithStatus(http.StatusInternalServerError)
return
}
ctx.String(http.StatusOK, doc)
default:
handler.ServeHTTP(ctx.Writer, ctx.Request)
}
}
}Durch den generierten Go-Code wird die Instanzregistrierung automatisch abgeschlossen. Unten steht ein Teil des Codes der automatisch generierten docs.go:
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = &swag.Spec{
Version: "",
Host: "",
BasePath: "",
Schemes: []string{},
Title: "",
Description: "",
InfoInstanceName: "swagger",
SwaggerTemplate: docTemplate,
LeftDelim: "{{",
RightDelim: "}}",
}
func init() {
// Instanz registrieren
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
}Wie Sie sehen, gibt es in der init-Funktion eine Register-Funktion zum Registrieren der aktuellen Instanz. Wenn Sie den Instanznamen ändern möchten, wird nicht empfohlen, dies in dieser Datei zu tun, da docs.go automatisch generiert wird. Verwenden Sie einfach den Parameter --instanceName appapi beim Generieren des Codes. Zur Vereinfachung können Sie den go generate-Befehl einbetten, um den Code automatisch zu generieren:
// swagger declarative api comment
// @title App Internal API Documentation
// @version v1.0.0
// @description Wilson api documentation
// @BasePath /api/v1
//go:generate swag init --generatedTime --instanceName appapi -g api.go -d ./ --output ./swaggerIch persönlich schreibe die allgemeinen Swagger-Informationskommentare nicht gerne in main.go oder auf die main-Funktion. Diese Kommentare über go generate zu schreiben, ist am besten geeignet.
TIP
Wenn Sie mehrere Instanzen benötigen, stellen Sie sicher, dass der Instanzname eindeutig ist, sonst tritt ein panic auf.
Für einige benutzerdefinierte Konfigurationen müssen Sie ginSwagger.CustomWrapHandler verwenden. Im Vergleich zum ersteren hat es einen zusätzlichen Config-Parameter mit folgender Bedeutung:
// Config stores ginSwagger configuration variables.
type Config struct {
// The url pointing to API definition (normally swagger.json or swagger.yaml). Default is `doc.json`.
URL string
// Schnittstellenlisten-Ausklappstatus
DocExpansion string
// Instanzname
InstanceName string
// Titel
Title string
// Ausklapptiefe
DefaultModelsExpandDepth int
// Der Name sagt alles
DeepLinking bool
PersistAuthorization bool
Oauth2DefaultClientID string
}Verwenden Sie swaggerFiles.NewHandler() anstelle des Standard-Handlers, besonders bei mehreren Instanzen.
engine.GET(openapi.ApiDoc, ginSwagger.CustomWrapHandler(openapi.Config, swaggerFiles.NewHandler()))Darüber hinaus sind auch Typ-Neuschreibungen und eine Reihe anderer Operationen möglich, die alle relativ einfach sind. Weitere Inhalte finden Sie in der offiziellen Dokumentation.
Hinweise
Swag generiert OpenAPI-Schnittstellenbeschreibungsdateien basierend auf Kommentaren. Beim Generieren muss das angegebene Verzeichnis die grundlegenden Informationen der API-Dokumentation enthalten. Standardmäßig wird in
main.gogesucht.swag initgibt standardmäßig das aktuelle Verzeichnis an, der Wert ist./. Sie können mehrere Verzeichnisse mitswag init -dangeben, durch Kommas getrennt. Das erste angegebene Verzeichnis muss die grundlegenden Informationen der API-Dokumentation enthalten. Zum Beispiel:swag init -d ./,./api-g: Die Datei für die grundlegenden Informationen der API-Dokumentation kann angepasst werden. Standardmäßig ist esmain.go. Verwenden Sie beim Generieren der Dokumentation den-g-Parameter, um den Dateinamen anzugeben:swag init -g api.go -d ./,./apiDieser Befehl bedeutet: Parse die grundlegenden Informationen der API-Dokumentation in
./api.gound durchsuche gleichzeitig die Verzeichnisse./und./apinach anderen Schnittstellenkommentaren, um die entsprechende Dokumentation zu generieren.Der
-o-Parameter kann den Ausgabepfad der Dokumentbeschreibungsdateien angeben. Standardmäßig ist es./docs. Zum Beispiel:swag init -o ./api/docs--otkann den Ausgabedateityp angeben. Standardmäßig sind es (docs.go, swagger.json, swagger.yaml). Wenn Sie ein Go-Programm zum Laden von Swagger UI verwenden möchten, ist die Go-Datei unverzichtbar.swag init --ot go,yamlDie übrigen generierten JSON- und YAML-Dateien können einfach in andere API-Verwaltungssoftware importiert werden.
Es ist egal, wo die Kommentare stehen. Selbst wenn sie nicht auf einer Funktion stehen, können sie geparst werden. Das Schreiben auf einer Funktion dient nur der besseren Lesbarkeit. Im Wesentlichen ist es eine DSL, die in Form von Kommentaren in den Go-Quellcode eingebettet ist.
Swag unterstützt viele weitere Parameter. Verwenden Sie
swag init -h, um sie anzuzeigen.
