Lägg till Swagger i Din Go API
Generera OpenAPI-dokument automatiskt från kodkommentarer
API-dokumentation är avgörande för någon modern applikation, och för Go APIs Swagger (OpenAPI) har blivit branschstandard. För Go-utvecklare erbjuder swaggo en elegant lösning för att generera omfattande API-dokumentation direkt från kodkommentarer.
Det här fina bilden är genererad av AI-modellen Flux 1 dev.
Varför Swagger är viktigt för Go-API:er
När man bygger REST-API:er blir dokumentationen ofta föråldrad när koden utvecklas. Swagger löser detta genom att generera dokumentation från din källkod, vilket säkerställer att den förblir synkroniserad med din implementation. Den interaktiva Swagger UI låter utvecklare testa slutpunkter direkt från webbläsaren, vilket betydligt förbättrar utvecklarupplevelsen.
För team som bygger mikrotjänster eller offentliga API:er blir Swagger-dokumentation avgörande för:
- Klientgenerering: Automatiskt skapa klientbibliotek på flera språk
- Kontraktstestning: Validera begäranden och svar mot definierade scheman
- Teamarbete: Erbjuda en enda sanningskälla för API-kontrakt
- Utvecklarintroduktion: Nya teammedlemmar kan utforska API:er interaktivt
Kom igång med swaggo
Swaggo-biblioteket är det mest populära verktyget för att lägga till Swagger-stöd till Go-applikationer. Det fungerar genom att tolka specialkommentarer i din kod och generera OpenAPI 3.0-specifikationsfiler.
Installation
Installera först swag CLI-verktyget:
go install github.com/swaggo/swag/cmd/swag@latest
Lägg sedan till den lämpliga Swagger-mellanhandsprogramspaketet för din ramverk. För Gin:
go get -u github.com/swaggo/gin-swagger
go get -u github.com/swaggo/files
För Echo:
go get -u github.com/swaggo/echo-swagger
För Fiber:
go get -u github.com/gofiber/swagger
Grundläggande konfiguration
Börja med att lägga till allmän API-information i din main.go fil. Liknande hur du skulle strukturera en REST API i Go, bör kommentarerna vara klara och beskrivande:
// @title Produkt API
// @version 1.0
// @description En produktförvaltnings-API med Swagger-dokumentation
// @termsOfService http://swagger.io/terms/
// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host localhost:8080
// @BasePath /api/v1
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
// @description Skriv "Bearer" följt av ett mellanslag och JWT-token.
func main() {
// Din applikationskod
}
Implementering med Gin-ramverk
Låt oss implementera ett komplett exempel med Gin. Börja med att definiera dina datamodeller med struct-taggar:
type Product struct {
ID int `json:"id" example:"1"`
Name string `json:"name" example:"Laptop" binding:"required"`
Description string `json:"description" example:"Högpresterande laptop"`
Price float64 `json:"price" example:"999.99" binding:"required,gt=0"`
Stock int `json:"stock" example:"50"`
}
type ErrorResponse struct {
Error string `json:"error" example:"Ogiltig inmatning"`
Message string `json:"message" example:"Produktnamn är obligatoriskt"`
}
Kommentera nu dina hanteringsfunktioner. När du arbetar med databashantering, hjälper dessa kommentarer att dokumentera dataflödet:
// GetProduct godoc
// @Summary Hämta produkt efter ID
// @Description Hämta en enda produkt efter dess unika identifierare
// @Tags products
// @Accept json
// @Produce json
// @Param id path int true "Produkt ID"
// @Success 200 {object} Product
// @Failure 400 {object} ErrorResponse
// @Failure 404 {object} ErrorResponse
// @Router /products/{id} [get]
func GetProduct(c *gin.Context) {
id := c.Param("id")
// Implementering här
c.JSON(200, Product{ID: 1, Name: "Laptop", Price: 999.99})
}
// CreateProduct godoc
// @Summary Skapa en ny produkt
// @Description Lägg till en ny produkt i katalogen
// @Tags products
// @Accept json
// @Produce json
// @Param product body Product true "Produkt objekt"
// @Success 201 {object} Product
// @Failure 400 {object} ErrorResponse
// @Security Bearer
// @Router /products [post]
func CreateProduct(c *gin.Context) {
var product Product
if err := c.ShouldBindJSON(&product); err != nil {
c.JSON(400, ErrorResponse{Error: "Bad Request", Message: err.Error()})
return
}
// Spara till databas
c.JSON(201, product)
}
Generera dokumentation
Efter att ha kommenterat din kod, generera Swagger-dokumentationen:
swag init
Detta skapar en docs mapp med swagger.json, swagger.yaml och Go-filer. Importera och registrera Swagger-slutpunkten:
package main
import (
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
_ "yourproject/docs" // Importera genererade dokument
)
func main() {
r := gin.Default()
// API-rutter
v1 := r.Group("/api/v1")
{
v1.GET("/products/:id", GetProduct)
v1.POST("/products", CreateProduct)
}
// Swagger-slutpunkt
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
r.Run(":8080")
}
Nu kan du komma åt din interaktiva API-dokumentation på http://localhost:8080/swagger/index.html.
Implementering med Echo-ramverk
Echo-användare följer ett liknande mönster men med Echo-specifikt mellanhandsprogram:
package main
import (
"github.com/labstack/echo/v4"
echoSwagger "github.com/swaggo/echo-swagger"
_ "yourproject/docs"
)
func main() {
e := echo.New()
// API-rutter
api := e.Group("/api/v1")
api.GET("/products/:id", getProduct)
api.POST("/products", createProduct)
// Swagger-slutpunkt
e.GET("/swagger/*", echoSwagger.WrapHandler)
e.Start(":8080")
}
Implementering med Fiber-ramverk
Fibers implementering är lika rak:
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/swagger"
_ "yourproject/docs"
)
func main() {
app := fiber.New()
// API-rutter
api := app.Group("/api/v1")
api.Get("/products/:id", getProduct)
api.Post("/products", createProduct)
// Swagger-slutpunkt
app.Get("/swagger/*", swagger.HandlerDefault)
app.Listen(":8080")
}
Avancerade Swagger-kommentarer
Dokumentera komplexa begärande kroppar
För inbäddade strukturer eller arrayer:
type CreateOrderRequest struct {
CustomerID int `json:"customer_id" example:"123" binding:"required"`
Items []OrderItem `json:"items" binding:"required,min=1"`
ShippingAddress Address `json:"shipping_address" binding:"required"`
}
type OrderItem struct {
ProductID int `json:"product_id" example:"1" binding:"required"`
Quantity int `json:"quantity" example:"2" binding:"required,min=1"`
}
type Address struct {
Street string `json:"street" example:"123 Main St" binding:"required"`
City string `json:"city" example:"New York" binding:"required"`
ZipCode string `json:"zip_code" example:"10001" binding:"required"`
}
// CreateOrder godoc
// @Summary Skapa en ny order
// @Description Skapa en order med flera artiklar och leveransinformation
// @Tags orders
// @Accept json
// @Produce json
// @Param order body CreateOrderRequest true "Order detaljer"
// @Success 201 {object} Order
// @Failure 400 {object} ErrorResponse
// @Failure 422 {object} ErrorResponse
// @Security Bearer
// @Router /orders [post]
func CreateOrder(c *gin.Context) {
// Implementering
}
Dokumentera filuppladdningar
// UploadImage godoc
// @Summary Ladda upp produktbild
// @Description Ladda upp en bildfil för en produkt
// @Tags products
// @Accept multipart/form-data
// @Produce json
// @Param id path int true "Produkt ID"
// @Param file formData file true "Bildfil"
// @Success 200 {object} map[string]string
// @Failure 400 {object} ErrorResponse
// @Security Bearer
// @Router /products/{id}/image [post]
func UploadImage(c *gin.Context) {
file, _ := c.FormFile("file")
// Hantera uppladdning
}
Sökparametrar och sidnumrering
// ListProducts godoc
// @Summary Lista produkter med sidnumrering
// @Description Hämta sidnummerad lista över produkter med valfri filtrering
// @Tags products
// @Accept json
// @Produce json
// @Param page query int false "Sidanummer" default(1)
// @Param page_size query int false "Antal per sida" default(10)
// @Param category query string false "Filtrera efter kategori"
// @Param min_price query number false "Minsta pris"
// @Param max_price query number false "Maximalt pris"
// @Success 200 {array} Product
// @Failure 400 {object} ErrorResponse
// @Router /products [get]
func ListProducts(c *gin.Context) {
// Implementering med sidnumrering
}
Autentisering och säkerhet
Dokumentera olika autentiseringsmetoder i ditt API. För multi-tenant-applikationer, är korrekt autentiseringsdokumentation avgörande:
Bearer Token-autentisering
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
// @description Skriv "Bearer" följt av ett mellanslag och JWT-token.
API-nyckel autentisering
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name X-API-Key
// @description API-nyckel för autentisering
OAuth2-autentisering
// @securitydefinitions.oauth2.application OAuth2Application
// @tokenUrl https://example.com/oauth/token
// @scope.write Ger skrivrättigheter
// @scope.admin Ger läsa och skrivrättigheter till administrativ information
Basic-autentisering
// @securityDefinitions.basic BasicAuth
Tillämpa säkerhet på specifika slutpunkter:
// @Security Bearer
// @Security ApiKeyAuth
Anpassa Swagger UI
Du kan anpassa Swagger UI:s utseende och beteende:
// Anpassad konfiguration
url := ginSwagger.URL("http://localhost:8080/swagger/doc.json")
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
// Med anpassad titel
r.GET("/swagger/*any", ginSwagger.WrapHandler(
swaggerFiles.Handler,
ginSwagger.URL("http://localhost:8080/swagger/doc.json"),
ginSwagger.DefaultModelsExpandDepth(-1),
))
För att inaktivera Swagger i produktion:
if os.Getenv("ENV") != "production" {
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
}
Integrering med CI/CD
Automatisera Swagger-dokumentationsgenerering i din CI/CD-pipeline:
# GitHub Actions exempel
name: Generera Swagger-dokumentation
on: [push]
jobs:
swagger:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Konfigurera Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
- name: Installera swag
run: go install github.com/swaggo/swag/cmd/swag@latest
- name: Generera Swagger-dokumentation
run: swag init
- name: Committa dokumentation
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git add docs/
git commit -m "Uppdatera Swagger-dokumentation" || exit 0
git push
Bästa praxis
1. Enhetlig kommenteringsstil
Håll enhetlig formatering över alla slutpunkter:
// HandlerName godoc
// @Summary Kort beskrivning (under 50 tecken)
// @Description Detaljerad beskrivning av vad slutpunkten gör
// @Tags resursnamn
// @Accept json
// @Produce json
// @Param namn plats typ obligatorisk "beskrivning"
// @Success 200 {object} Svarstyp
// @Failure 400 {object} FelSvar
// @Router /sökväg [metod]
2. Använd beskrivande exempel
Lägg till realistiska exempel för att hjälpa API-användare:
type Användare struct {
ID int `json:"id" example:"1"`
Email string `json:"email" example:"användare@example.com"`
Skapad time.Time `json:"skapad" example:"2025-01-15T10:30:00Z"`
}
3. Dokumentera alla svarskoder
Inkludera alla möjliga HTTP-statuskoder:
// @Success 200 {object} Produkt
// @Success 201 {object} Produkt
// @Failure 400 {object} FelSvar "Ogiltig begäran"
// @Failure 401 {object} FelSvar "Ej auktoriserad"
// @Failure 403 {object} FelSvar "Förbjuden"
// @Failure 404 {object} FelSvar "Hittades inte"
// @Failure 422 {object} FelSvar "Valideringsfel"
// @Failure 500 {object} FelSvar "Internt serverfel"
4. Versionshantera ditt API
Använd korrekt versionshantering i basväg:
// @BasePath /api/v1
Och organisera din kod därefter:
v1 := r.Group("/api/v1")
v2 := r.Group("/api/v2")
5. Gruppera relaterade slutpunkter
Använd taggar för att logiskt organisera slutpunkter:
// @Tags produkter
// @Tags beställningar
// @Tags användare
6. Håll dokumentationen uppdaterad
Kör swag init innan varje commit eller integrera det i din byggprocess:
#!/bin/bash
# pre-commit-hook
swag init
git add docs/
Testning av Swagger-dokumentation
När du arbetar med serverlösa arkitekturer som AWS Lambda blir det ännu viktigare att testa din API-dokumentation:
func TestSwaggerGenerering(t *testing.T) {
// Verifiera att swagger.json finns
_, err := os.Stat("./docs/swagger.json")
if err != nil {
t.Fatal("swagger.json hittades inte, kör 'swag init'")
}
// Verifiera att swagger-slutpunkten svarar
r := setupRouter()
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/swagger/index.html", nil)
r.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
}
Vanliga problem och lösningar
Dokumentation uppdateras inte
Om ändringar inte visas, se till att du återskapar dokumentationen:
swag init --parseDependency --parseInternal
Flaggan --parseDependency parser externa beroenden, och --parseInternal parser interna paket.
Anpassade typer erkänns inte
För typer från externa paket, använd swaggertype-taggen:
type AnpassadTid struct {
time.Time
}
func (AnpassadTid) SwaggerDoc() map[string]string {
return map[string]string{
"tid": "RFC3339-tidsstämpel",
}
}
Eller använd swaggertype-taggen:
type Produkt struct {
ID int `json:"id"`
Uppdaterad AnpassadTid `json:"uppdaterad" swaggertype:"string" format:"date-time"`
}
Arrayer och enumereringar
Dokumentera arraytyper och enumereringar:
type Filter struct {
Status []string `json:"status" enums:"aktiv,inaktiv,väntande"`
Taggar []string `json:"taggar"`
}
// @Param status query string false "Statusfilter" Enums(aktiv, inaktiv, väntande)
Alternativa tillvägagångssätt
Medan swaggo är det mest populära valet finns andra alternativ:
go-swagger
Ett mer funktionellt men komplext alternativ:
brew install go-swagger
swagger generate spec -o ./swagger.json
Manuella OpenAPI-filer
För full kontroll, skriv OpenAPI-specifikationer manuellt i YAML:
openapi: 3.0.0
info:
title: Produkt API
version: 1.0.0
paths:
/produkter:
get:
summary: Lista produkter
responses:
'200':
description: Lyckades
Därefter servera med:
r.StaticFile("/openapi.yaml", "./openapi.yaml")
Integrering med AI och LLMs
När du bygger API:er som integreras med AI-tjänster blir korrekt dokumentation avgörande. Till exempel, när du arbetar med strukturerade LLM-utdata, hjälper Swagger dokumentera komplexa begärans- och svarscheman:
type LLMFörfrågan struct {
Prompt string `json:"prompt" example:"Sammanfatta denna text"`
Modell string `json:"modell" example:"qwen2.5:latest"`
Temperatur float64 `json:"temperatur" example:"0.7" minimum:"0" maximum:"2"`
MaxTokens int `json:"max_tokens" example:"1000" minimum:"1"`
Schema map[string]interface{} `json:"schema,omitempty"`
}
// GenereraStrukturerad godoc
// @Summary Generera strukturerad LLM-utdata
// @Description Generera text med begränsad utdata-schema
// @Tags llm
// @Accept json
// @Produce json
// @Param förfrågan body LLMFörfrågan true "LLM-parametrar"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} FelSvar
// @Router /llm/generera [post]
func GenereraStrukturerad(c *gin.Context) {
// Implementering
}
Prestandaöverväganden
Swagger-dokumentation har minimal prestandapåverkan:
- Byggtid:
swag inittar 1-3 sekunder för de flesta projekt - Körtid: Dokumentationen laddas en gång vid start
- Minne: Lägger till 1-2MB till binärstorleken
- Svarstid: Ingen påverkan på API-slutpunkterna själva
För mycket stora API:er (100+ slutpunkter), överväg:
- Att dela upp i flera Swagger-filer
- Att lata ladda Swagger UI-assets
- Att servera dokumentationen från en separat tjänst
Säkerhetsöverväganden
När du exponerar Swagger-dokumentation:
- Inaktivera i produktion (om API är internt):
if os.Getenv("MILJÖ") == "produktion" {
// Registrera inte Swagger-slutpunkten
return
}
- Lägg till autentisering:
auktoriserad := r.Group("/swagger")
auktoriserad.Use(AuthMiddleware())
auktoriserad.GET("/*allt", ginSwagger.WrapHandler(swaggerFiles.Handler))
- Begränsa hastigheten på slutpunkten:
r.GET("/swagger/*allt", RateLimitMiddleware(), ginSwagger.WrapHandler(swaggerFiles.Handler))
- Exponera aldrig interna detaljer:
- Dokumentera inte interna slutpunkter
- Undvik att exponera databasscheman direkt
- Sanitera felmeddelanden i dokumentationen
Slutsats
Att lägga till Swagger-dokumentation till ditt Go-API förvandlar utvecklarupplevelsen från gissande till vägledd utforskning. Swaggo-biblioteket gör denna process enkel genom att generera omfattande OpenAPI-dokumentation från dina kodkommentarer.
Viktiga slutsatser:
- Börja med grundläggande kommentarer och utöka gradvis
- Håll dokumentationen synkroniserad med koden genom CI/CD
- Använd Swagger UI för interaktiv testning under utveckling
- Dokumentera autentisering, fel och gränssituationer grundligt
- Överväg säkerhetsimplikationerna när du exponerar dokumentationen
Oavsett om du bygger mikrotjänster, offentliga API:er eller interna verktyg, betalar Swagger-dokumentation av sig i minskad supportbelastning, snabbare introduktion och bättre API-design. Den initiala investeringen i att lära sig kommenteringssyntax blir snart rutin, och automatisk generering säkerställer att din dokumentation aldrig hamnar efter din implementering.
För Go-utvecklare skapar kombinationen av stark typning, kodgenerering och swaggos kommenteringssystem ett kraftfullt arbetsflöde som gör API-dokumentation till en naturlig del av utvecklingsprocessen istället för en eftertanke.
Användbara länkar
- Go Cheatsheet
- Att bygga REST API:er i Go
- Jämförelse av Go ORMs för PostgreSQL: GORM vs Ent vs Bun vs sqlc
- Multi-Tenancy Database-mönster med exempel i Go
- LLMs med strukturerad utdata: Ollama, Qwen3 & Python eller Go
- AWS lambda-prestanda: JavaScript vs Python vs Golang