swag
swaggo/swag adalah implementasi Swagger API 2.0 dalam bahasa Go dengan menulis komentar format tertentu dapat menghasilkan file dokumentasi interface swagger.json dan swagger.yaml mudah untuk export dan import.
Repositori: swaggo/swag: Automatically generate RESTful API documentation with Swagger 2.0 for Go. (github.com)
Dokumentasi: swaggo/swag: Automatically generate RESTful API documentation with Swagger 2.0 for Go. (github.com)
swag mendukung framework web default sebagai berikut artikel ini menggunakan gin sebagai contoh untuk mendemonstrasikan contoh menghasilkan dokumentasi interface dengan cepat menggunakan gin dan swagger.
TIP
Jika tidak familiar dengan sintaks swagger dapat pergi ke About Swagger Specification | Documentation | Swagger
Instalasi
Pertama download tool command line swagger
go install github.com/swaggo/swag/cmd/swag@latestKemudian download dependensi source code swagger
go get github.com/swaggo/swagTIP
Untuk menghindari masalah versi keduanya harus konsisten.
Kemudian download library file statis swagger html css js dan lain-lain semuanya tertanam dalam kode Go.
go get github.com/swaggo/files@latestTerakhir download library adaptasi gin swagger
go get github.com/swaggo/gin-swagger@latestKarena artikel ini hanya menggunakan gin sebagai contoh adaptor framework web lainnya dapat dipelajari sendiri pada dasarnya hampir sama.
Penggunaan
Gunakan go mod untuk membuat proyek Go paling dasar buat main.go tulis konten berikut.
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")),
})
}Ini adalah contoh gin web yang sangat sederhana komentar pada fungsi main adalah informasi dasar dokumentasi fungsi Ping adalah interface biasa. Selanjutnya jalankan command untuk menghasilkan dokumentasi default berada di direktori docs yang setara dengan main.go
swag initModifikasi kode main.go
package main
import (
"fmt"
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
// anonymous import paket dokumentasi interface yang dihasilkan
_ "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()
// mendaftarkan route statis 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")),
})
}Jalankan program akses 127.0.0.1/swagger/index.html interface sebagai berikut

Dengan demikian telah menjalankan dokumentasi interface dasar. Selanjutnya kecuali beberapa poin yang perlu diperhatikan pada dasarnya tidak ada perbedaan besar dengan bahasa lain.
Parameter
Format definisi parameter adalah
@param name paramtype datatype isRequired commentSatu contoh sebagai berikut
@param userId query int true "user unique id"Di antara jenis parameter yang didukung adalah
- query
- path
- header
- body
- formData
Jenis data adalah
- string (string)
- integer (int, uint, uint32, uint64)
- number (float32)
- boolean (bool)
- user defined struct
Jenis parameter juga dapat menjadi jenis Anda sendiri asalkan dapat dipindai oleh swagger.
Response
Format dasar definisi response interface adalah sebagai berikut
// @Success 200 {array} model.Account
// @Failure 400 {object} httputil.HTTPError
// @Failure 404 {object} httputil.HTTPError
// @Failure 500 {object} httputil.HTTPErrorTerdiri dari status code jenis dasar jenis data. {array} menunjukkan adalah array akan menampilkan bentuk array jenis data {object} akan menampilkan bentuk asli jenis data. Misalnya biasanya kita akan mendefinisikan response body terpadu
type JSONResult struct {
Code int `json:"code" `
Message string `json:"message"`
Data interface{} `json:"data"`
}Jenis field Data tidak pasti saat mendeskripsikan use case response dapat dikombinasikan sebagai berikut
// Kombinasi
@success 200 {object} jsonresult.JSONResult{data=Account} "desc"
// Array
@success 200 {object} jsonresult.JSONResult{data=[]Account} "desc"Model
Menambahkan komentar field struct akan dipindai oleh swagger sebagai field komentar model
package model
type Account struct {
// account id
ID int `json:"id" example:"1"`
// username
Name string `json:"name" example:"account name"`
}Di antara nilai tag example akan ditampilkan sebagai nilai contoh di halaman tentu saja juga mendukung batasan field
type Foo struct {
Bar string `minLength:"4" maxLength:"16"`
Baz int `minimum:"10" maximum:"20" default:"15"`
Qux []string `enums:"foo,bar,baz"`
}Semua model saat digunakan harus memastikan dapat dipindai oleh swagger jika tidak tidak akan berfungsi.
Autentikasi
Dalam hal autentikasi mendukung
- Basic Auth
- API Key
- OAuth2 app auth
- OAuth2 implicit auth
- OAuth2 password auth
- OAuth2 access code auth
Jika autentikasi interface menggunakan JWT disimpan di field Authorization di header kita dapat mendefinisikan sebagai berikut
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
Pada dasarnya ini hanya apikey jika Anda mengirimkan bearer token perlu menambahkan prefix Bearer secara manual.

Kemudian di interface yang memerlukan autentikasi tambahkan komentar berikut
// @security BearerNilainya adalah nama definisi securityDefinitions Anda.
Konfigurasi
swag sebenarnya menyimpan beberapa instance swagger berbeda dalam map ginSwagger sebagai adaptor membaca doc.json dari instance yaitu file definisi interface API swaggerFiles menyediakan file HTML statis untuk menampilkan halaman web mengurai definisi API dan menghasilkan interface setelah memahami seluruh proses dapat melakukan operasi kustom.
// Name is a unique name be used to register swag instance.
// nama instance default
const Name = "swagger"
var (
swaggerMu sync.RWMutex
// tabel instance
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"
}
// membuat template dengan nama
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
}
// pencocokan route
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 {
// halaman utama
case "index.html":
_ = index.Execute(ctx.Writer, config.toSwaggerConfig())
// file deskripsi 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)
}
}
}Melalui kode Go yang dihasilkan secara otomatis menyelesaikan registrasi instance di bawah adalah sebagian kode docs.go yang dihasilkan secara otomatis
// 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() {
// registrasi instance
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
}Dapat dilihat ada fungsi Register di fungsi init yang digunakan untuk registrasi instance saat ini jika ingin mengubah nama instance tidak disarankan untuk mengedit di file ini karena file docs.go dihasilkan secara otomatis hanya perlu menggunakan parameter --instanceName appapi saat menghasilkan kode. Untuk kenyamanan dapat menggunakan command go generate yang tertanam dalam file Go untuk memudahkan menghasilkan kode secara otomatis sebagai berikut.
// 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 ./swaggerSecara pribadi tidak suka menulis komentar umum swagger di main.go atau fungsi main menulis komentar ini di atas go generate paling tepat.
TIP
Jika memerlukan beberapa instance pastikan nama instance unik jika tidak akan panic
Untuk mengustomisasi beberapa konfigurasi perlu menggunakan ginSwagger.CustomWrapHandler dibandingkan yang sebelumnya memiliki parameter Config tambahan penjelasannya sebagai berikut
// Config stores ginSwagger configuration variables.
type Config struct {
// url yang menunjuk ke definisi API (biasanya swagger.json atau swagger.yaml). Default adalah `doc.json`.
URL string
// status expand daftar interface
DocExpansion string
// nama instance
InstanceName string
// judul
Title string
// kedalaman expand
DefaultModelsExpandDepth int
// sesuai namanya
DeepLinking bool
PersistAuthorization bool
Oauth2DefaultClientID string
}Gunakan swaggerFiles.NewHandler() untuk menggantikan Handler default terutama saat menggunakan beberapa instance.
engine.GET(openapi.ApiDoc, ginSwagger.CustomWrapHandler(openapi.Config, swaggerFiles.NewHandler()))Selain itu juga dapat melakukan operasi seperti rewrite jenis dan lain-lain semuanya cukup sederhana konten lebih lanjut dapat membaca dokumentasi resmi.
Perhatian
swag menghasilkan file deskripsi interface openapi berdasarkan komentar saat menghasilkan direktori yang ditentukan harus berisi informasi dasar dokumentasi interface default dicari di
main.goswag initdefault menentukan direktori saat ini nilainya./dapat menggunakanswag init -duntuk menentukan beberapa direktori gunakan koma untuk memisahkan direktori yang ditentukan pertama harus berisi informasi dasar dokumentasi interface. Misalnyaswag init -d ./,./api-gnama file tempat informasi dasar dokumentasi interface disimpan dapat dikustomisasi default adalahmain.gosaat menghasilkan dokumentasi gunakan parameter-guntuk menentukan nama fileswag init -g api.go -d ./,./apiCommand ini berarti mengurai informasi dasar dokumentasi interface di
./api.gosekaligus mencari dan mengurai informasi komentar interface lain di direktori./dan./apidan menghasilkan dokumentasi yang sesuai.Parameter
-odapat menentukan path output file deskripsi dokumentasi default adalah./docscontoh:swag init -o ./api/docs--otdapat menentukan jenis file output default adalah (docs.go,swagger.json,swagger.yaml) jika ingin menggunakan program Go untuk memuat swagger ui file Go sangat diperlukan.swag init --ot go,yamlFile json dan yaml yang dihasilkan sisanya dapat dengan mudah mengimpor data di software manajemen interface lainnya.
Menulis komentar di mana saja sama bahkan jika tidak ditulis di fungsi juga dapat diurai hanya saja menulis di fungsi lebih baik readability pada dasarnya masih DSL yang tertanam dalam bentuk komentar dan source code Go.
swag juga mendukung banyak parameter lainnya dapat menggunakan
swag init -huntuk melihat.
