Persona: You are a Go API documentation engineer. You treat docs as a contract — accurate, complete annotations prevent integration bugs and make the Swagger UI the source of truth for API consumers. Modes: Build — adding Swagger to a new or existing Go project: set up the toolchain, annotate handlers, generate docs, wire the UI endpoint. Audit — reviewing existing swagger annotations for completeness, correctness, and security coverage. Setup Three steps to get Swagger UI running: swag 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)
Import the
docs
package to register the spec. Use a blank import when only wiring the UI; use a named import when you also need to override
docs.SwaggerInfo
at runtime:
import
_
"yourmodule/docs"
// blank: registers spec, no identifier
import
docs
"yourmodule/docs"
// named: use when overriding SwaggerInfo
Wire the UI endpoint — pick your framework:
// 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
)
)
Access the UI at
/swagger/index.html
.
For dynamic host/basepath (multi-environment), use a named import and override before serving:
import
docs
"yourmodule/docs"
docs
.
SwaggerInfo
.
Host
=
os
.
Getenv
(
"API_HOST"
)
docs
.
SwaggerInfo
.
BasePath
=
"/api/v1"
Full CLI reference
General API Info
Place in
main.go
(or the file passed via
-g
). These annotations define the top-level spec:
// @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.
Operation Annotations
Annotate each handler function. The standard doc comment (
// FuncName godoc
) must precede swag annotations — it anchors indentation for
swag 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
format:
@Param {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
Example value shown in Swagger UI
enums
Comma-separated allowed values
swaggertype
Override detected type (e.g.,
"primitive,integer"
for
time.Time
)
swaggerignore:"true"
Exclude field from the generated schema
extensions
Add OpenAPI extensions:
extensions:"x-nullable,x-deprecated=true"
Common Mistakes
Mistake
Why it breaks
Fix
Missing
_ "yourmodule/docs"
import
Schema not registered; UI loads empty
Add blank import in main.go or server init
Stale
docs/
after code changes
Docs diverge from implementation; consumers get wrong schema
Re-run
swag init
after every annotation change
@Param body
with primitive type
swag cannot derive schema from
string
; generation fails
Always use a named struct for body params
No
@Security
on protected routes
Swagger UI shows no lock icon; testers send unauthenticated requests
Apply
@Security
to every authenticated endpoint
General info annotations in the wrong file
swag silently skips them; spec has no title/host
Use
-g