Loading...
Loading...
Golang OpenAPI/Swagger documentation with swaggo/swag — annotation comments (@Summary, @Param, @Success, @Router, @Security), swag init code generation, framework integrations (gin, echo, fiber, chi, net/http), security definitions (Bearer/JWT, OAuth2, API key), and struct tags (swaggertype, enums, example, swaggerignore). Apply when adding or maintaining Swagger/OpenAPI docs in a Go project, or when the codebase imports github.com/swaggo/swag, github.com/swaggo/gin-swagger, github.com/swaggo/echo-swagger, github.com/swaggo/http-swagger, or github.com/swaggo/files.
npx skill4agent add samber/cc-skills-golang golang-swaggerswag init # generates docs/ with docs.go, swagger.json, swagger.yaml
swag init -g cmd/api/main.go # if general info is not in main.go
swag fmt # format annotation comments (like go fmt)docsdocs.SwaggerInfoimport _ "yourmodule/docs" // blank: registers spec, no identifier
import docs "yourmodule/docs" // named: use when overriding SwaggerInfo// Gin
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
// Echo
e.GET("/swagger/*", echoSwagger.WrapHandler)
// Fiber
app.Get("/swagger/*", fiberSwagger.WrapHandler(swaggerFiles.Handler))
// net/http
mux.Handle("/swagger/", httpSwagger.Handler(swaggerFiles.Handler))
// Chi
r.Get("/swagger/*", httpSwagger.Handler(swaggerFiles.Handler))/swagger/index.htmlimport docs "yourmodule/docs"
docs.SwaggerInfo.Host = os.Getenv("API_HOST")
docs.SwaggerInfo.BasePath = "/api/v1"main.go-g// @title My API
// @version 1.0
// @description Short description of the API.
// @host localhost:8080
// @BasePath /api/v1
// @schemes http https
// @contact.name API Support
// @contact.email support@example.com
// @license.name Apache 2.0
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
// @description Type "Bearer" followed by a space and the JWT token.// FuncName godocswag fmt// ShowAccount godoc
// @Summary Get account by ID
// @Description Returns account details for the given ID.
// @Tags accounts
// @Accept json
// @Produce json
// @Param id path int true "Account ID"
// @Param filter query string false "Optional search filter"
// @Success 200 {object} model.Account
// @Success 204 "No content"
// @Failure 400 {object} api.ErrorResponse
// @Failure 404 {object} api.ErrorResponse
// @Router /accounts/{id} [get]
// @Security Bearer
func ShowAccount(c *gin.Context) {}@Param <name> <in> <type> <required> "<description>" [attributes] | Usage |
|---|---|
| URL path segment ( |
| URL query string ( |
| Request body — type must be a struct |
| HTTP header |
| Multipart/form field |
@Paramdefault(v)minimum(n)maximum(n)minLength(n)maxLength(n)Enums(a,b,c)example(v)collectionFormat(multi)@Success <code> {<kind>} <type> "<description>" | When |
|---|---|
| Single struct |
| Slice of structs |
| Primitive |
@Success 200 {object} api.Response[model.User]@Success 200 {object} api.Response{data=model.User}@Security// Bearer / JWT
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
// API key in header
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name X-API-Key
// Basic auth
// @securityDefinitions.basic BasicAuth
// OAuth2 authorization code
// @securityDefinitions.oauth2.authorizationCode OAuth2
// @authorizationUrl https://example.com/oauth/authorize
// @tokenUrl https://example.com/oauth/token
// @scope.read Read access
// @scope.write Write access// @Security Bearer
// @Security OAuth2[read, write]
// @Security BasicAuth && ApiKeyAuth // AND — both requiredtype CreateUserRequest struct {
Name string `json:"name" example:"Jane Doe" minLength:"2" maxLength:"100"`
Role string `json:"role" enums:"admin,user,guest" example:"user"`
Age int `json:"age" minimum:"18" maximum:"120"`
Avatar []byte `json:"avatar" swaggertype:"string" format:"base64"`
Secret string `json:"-" swaggerignore:"true"` // excluded from docs
}| Tag | Purpose |
|---|---|
| Example value shown in Swagger UI |
| Comma-separated allowed values |
| Override detected type (e.g., |
| Exclude field from the generated schema |
| Add OpenAPI extensions: |
| Mistake | Why it breaks | Fix |
|---|---|---|
Missing | Schema not registered; UI loads empty | Add blank import in main.go or server init |
Stale | Docs diverge from implementation; consumers get wrong schema | Re-run |
| swag cannot derive schema from | Always use a named struct for body params |
No | Swagger UI shows no lock icon; testers send unauthenticated requests | Apply |
| General info annotations in the wrong file | swag silently skips them; spec has no title/host | Use |
Using | swag cannot generate a schema for | Use a named struct or annotate with |
Multi-word | Tags split on spaces, producing malformed grouping | Quote tags with spaces: |
samber/cc-skills-golang@golang-securitysamber/cc-skills-golang@golang-grpc