swag
swaggo/swag は Go 言語における Swagger API 2.0 の実装で、指定フォーマットのコメントを記述するだけで swagger.json や swagger.yaml 形式のインターフェースドキュメントを生成でき、エクスポートやインポートに便利です。
リポジトリ:swaggo/swag: Automatically generate RESTful API documentation with Swagger 2.0 for Go. (github.com)
ドキュメント:swaggo/swag: Automatically generate RESTful API documentation with Swagger 2.0 for Go. (github.com)
swag がデフォルトでサポートする Web フレームワークは以下の通りです。本文では gin を例として、gin と swagger を組み合わせてインターフェースドキュメントを迅速に生成する例を示します。
TIP
swagger の構文に不慣れな場合は、About Swagger Specification | Documentation | Swagger を参照してください。
インストール
まず swagger コマンドラインツールをダウンロードします。
go install github.com/swaggo/swag/cmd/swag@latest次に swagger ソースコード依存関係をダウンロードします。
go get github.com/swaggo/swagTIP
問題が発生しないよう、両者のバージョンは一致させる必要があります。
次に swagger の静的ファイルライブラリ(html、css、js など)をダウンロードします。これらは Go コードに埋め込まれています。
go get github.com/swaggo/files@latest最後に swagger の gin 適応ライブラリをダウンロードします。
go get github.com/swaggo/gin-swagger@latest本文では gin のみを例として使用しているため、他の Web フレームワークのアダプターについては自行で調べてください。基本的にほぼ同じです。
使用方法
go mod を使用して最も基本的な Go プロジェクトを作成し、main.go を新規作成して以下の内容を記述します。
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")),
})
}これは非常にシンプルな gin Web の例で、main 関数のコメントはドキュメントの基本情報、Ping 関数は通常のインターフェースです。次にコマンドを実行してドキュメントを生成します。デフォルトでは main.go と同じディレクトリの docs ディレクトリに生成されます。
swag initmain.go コードを修正します。
package main
import (
"fmt"
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
// 生成されたインターフェースドキュメントパッケージを匿名インポート
_ "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 静的ファイルルートを登録
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")),
})
}プログラムを実行し、127.0.0.1/swagger/index.html にアクセスすると、インターフェースは以下のようになります。

これで基本的なインターフェースドキュメントが実行されました。次に特に注意すべき点を除けば、基本的に他の言語での使用と大きな違いはありません。
パラメータ
パラメータを定義する形式は以下の通りです。
@param name paramtype datatype isRequired comment例は以下の通りです。
@param userId query int true "user unique id"サポートされるパラメータタイプは以下の通りです。
- query
- path
- header
- body
- formData
データタイプは以下の通りです。
- string (string)
- integer (int, uint, uint32, uint64)
- number (float32)
- boolean (bool)
- ユーザー定義構造体
パラメータタイプは独自のタイプにすることもできます。swagger でスキャン可能である必要があります。
レスポンス
インターフェースレスポンスを定義する基本形式は以下の通りです。
// @Success 200 {array} model.Account
// @Failure 400 {object} httputil.HTTPError
// @Failure 404 {object} httputil.HTTPError
// @Failure 500 {object} httputil.HTTPErrorステータスコード、基本タイプ、データタイプで構成されます。{array} は配列であることを示し、データタイプの配列形式で表示されます。{object} はデータタイプの元の形式で表示されます。例えば、通常は統一されたレスポンスボディを定義します。
type JSONResult struct {
Code int `json:"code" `
Message string `json:"message"`
Data interface{} `json:"data"`
}Data フィールドのタイプは不確定です。レスポンス例を記述する際に、以下のように組み合わせることができます。
// 組み合わせ
@success 200 {object} jsonresult.JSONResult{data=Account} "desc"
// 配列
@success 200 {object} jsonresult.JSONResult{data=[]Account} "desc"モデル
構造体フィールドにコメントを追加すると、swagger によってモデルフィールドコメントとしてスキャンされます。
package model
type Account struct {
// account id
ID int `json:"id" example:"1"`
// username
Name string `json:"name" example:"account name"`
}example タグの値はページにサンプル値として表示されます。もちろん、フィールド制限もサポートしています。
type Foo struct {
Bar string `minLength:"4" maxLength:"16"`
Baz int `minimum:"10" maximum:"20" default:"15"`
Qux []string `enums:"foo,bar,baz"`
}すべてのモデルは使用時に swagger でスキャン可能であることを確認する必要があります。否则不会起作用。
認証
認証では以下をサポートしています。
- Basic Auth
- API Key
- OAuth2 app auth
- OAuth2 implicit auth
- OAuth2 password auth
- OAuth2 access code auth
インターフェース認証に JWT を使用し、header の Authorization フィールドに保存する場合、以下のように定義できます。
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
本質的にはこれは apikey に過ぎません。bearer token を伝送する場合は、Bearer プレフィックスを手動で追加する必要があります。

次に認証が必要なインターフェースに以下のコメントを追加します。
// @security Bearerこの値は securityDefinitions で定義された名前です。
設定
swag は実際には複数の異なる swagger インスタンスを 1 つの map に保存し、ginSwagger はアダプターとしてインスタンスから doc.json(つまり API インターフェース定義ファイル)を読み取り、swaggerFiles は Web ページを表示するための静的 HTML ファイルを提供し、API 定義を解析してインターフェースを生成します。このプロセスを理解した後、カスタム操作を行うことができます。
// Name は swag インスタンスを登録するために使用される一意の名前です。
// デフォルトインスタンス名
const Name = "swagger"
var (
swaggerMu sync.RWMutex
// インスタンステーブル
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"
}
// 名前でテンプレートを作成
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
}
// ルートマッチング
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 {
// メインページ
case "index.html":
_ = index.Execute(ctx.Writer, config.toSwaggerConfig())
// API 記述ファイル
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)
}
}
}生成された Go コードを通じてインスタンス登録を自動的に完了します。以下は自動的に生成された docs.go の一部コードです。
// SwaggerInfo はエクスポートされた Swagger Info を保持し、クライアントが変更できるようにします
var SwaggerInfo = &swag.Spec{
Version: "",
Host: "",
BasePath: "",
Schemes: []string{},
Title: "",
Description: "",
InfoInstanceName: "swagger",
SwaggerTemplate: docTemplate,
LeftDelim: "{{",
RightDelim: "}}",
}
func init() {
// インスタンスを登録
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
}init 関数には現在のインスタンスを登録するための Register 関数があることがわかります。インスタンス名を変更したい場合は、このファイルを編集することはお勧めしません。docs.go ファイルは自動的に生成されるため、コード生成時に --instanceName appapi パラメータを使用するだけです。便宜のため、go generate コマンドを使用して Go ファイルに埋め込み、自動コード生成を容易にできます。以下のようにします。
// 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 ./swagger個人としては swagger の共通情報コメントを main.go または main 関数に記述することは好きではありません。これらのコメントを go generate の上に記述するのが最も適しています。
TIP
複数のインスタンスが必要な場合は、インスタンス名を一意に保つ必要があります。否则 panic します。
設定をカスタマイズするには、ginSwagger.CustomWrapHandler を使用する必要があります。前者より Config パラメータが 1 つ多く、意味は以下の通りです。
// Config は ginSwagger 設定変数を保存します。
type Config struct {
// API 定義を指す URL(通常は swagger.json または swagger.yaml)。デフォルトは `doc.json`。
URL string
// インターフェースリスト展開状態
DocExpansion string
// インスタンス名
InstanceName string
// タイトル
Title string
// 展開深度
DefaultModelsExpandDepth int
// 名前の通り
DeepLinking bool
PersistAuthorization bool
Oauth2DefaultClientID string
}swaggerFiles.NewHandler() を使用してデフォルトの Handler を置き換えます。複数のインスタンスの場合は特に如此です。
engine.GET(openapi.ApiDoc, ginSwagger.CustomWrapHandler(openapi.Config, swaggerFiles.NewHandler()))これに加えて、タイプ書き換えなどの一連の操作も可能です。これらはすべて比較的簡単です。詳細は公式ドキュメントを参照してください。
注意事項
swag はコメントに基づいて openapi のインターフェース記述ファイルを生成します。生成時、指定されたディレクトリにはインターフェースドキュメントの基本情報を含める必要があります。デフォルトでは
main.goで検索されます。swag initはデフォルトで現在のディレクトリを指定し、値は./です。swag init -dを使用して複数のディレクトリを指定できます。カンマで区切り、最初に指定されたディレクトリにはインターフェースドキュメントの基本情報を含める必要があります。例えばswag init -d ./,./api-g、インターフェースドキュメントの基本情報の保存ファイルはカスタムファイル名にできます。デフォルトはmain.goです。ドキュメント生成時に-gパラメータを使用してファイル名を指定します。swag init -g api.go -d ./,./apiこのコマンドの意味は、
./api.goでインターフェースドキュメントの基本情報を解析し、同時に./と./apiの 2 つのディレクトリで他のインターフェースのコメント情報を検索・解析して対応するドキュメントを生成することです。-oパラメータはドキュメント記述ファイルの出力パスを指定できます。デフォルトは./docsです。例:swag init -o ./api/docs--otは出力ファイルタイプを指定できます。デフォルトは(docs.go,swagger.json,swagger.yaml)です。swagger ui を Go プログラムで読み込む場合は、go ファイルが不可欠です。swag init --ot go,yamlその他生成された json と yaml ファイルは、他のインターフェース管理ソフトウェアでデータをインポートするのに便利です。
コメントをどこに記述しても同じです。関数上に記述しなくても解析できます。関数上に記述するのは可読性が良いだけです。本質的にはコメント形式と Go ソースコードが一緒に埋め込まれた DSL です。
swag は多くの他のパラメータもサポートしています。
swag init -hを使用して確認できます。
