💻 Exemplos: Capítulo 18: Documentação de API Swagger com Swag e Gin-Swagger
Especialização em Backend com Go & Gin • Demonstrações Práticas Compiláveis
💻 Código de Exemplo 01 — Handlers Anotados com Swag (CRUD de Pedidos)
package handlers
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
// PedidoResponse representa o schema de resposta documentado no Swagger.
type PedidoResponse struct {
ID int `json:"id" example:"42"`
Status string `json:"status" example:"processando"`
Valor float64 `json:"valor" example:"199.90"`
}
// ErroResponse é o schema padrão de erro usado em todas as rotas @Failure.
type ErroResponse struct {
Mensagem string `json:"mensagem" example:"pedido não encontrado"`
}
// ObterPedido godoc
// @Summary Obter pedido por ID
// @Description Retorna os detalhes de um pedido específico
// @Tags Pedidos
// @Produce json
// @Param id path int true "ID do pedido"
// @Success 200 {object} PedidoResponse
// @Failure 404 {object} ErroResponse
// @Security BearerAuth
// @Router /pedidos/{id} [get]
func ObterPedido(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, ErroResponse{Mensagem: "id inválido"})
return
}
if id != 42 {
c.JSON(http.StatusNotFound, ErroResponse{Mensagem: "pedido não encontrado"})
return
}
c.JSON(http.StatusOK, PedidoResponse{ID: id, Status: "processando", Valor: 199.90})
}
// CriarPedidoRequest é o corpo esperado para criação de pedido.
type CriarPedidoRequest struct {
ClienteID int `json:"cliente_id" binding:"required" example:"7"`
Valor float64 `json:"valor" binding:"required,gt=0" example:"150.00"`
}
// CriarPedido godoc
// @Summary Criar novo pedido
// @Description Cria um pedido a partir do corpo JSON informado
// @Tags Pedidos
// @Accept json
// @Produce json
// @Param pedido body CriarPedidoRequest true "Dados do pedido"
// @Success 201 {object} PedidoResponse
// @Failure 400 {object} ErroResponse
// @Security BearerAuth
// @Router /pedidos [post]
func CriarPedido(c *gin.Context) {
var req CriarPedidoRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, ErroResponse{Mensagem: err.Error()})
return
}
c.JSON(http.StatusCreated, PedidoResponse{ID: 99, Status: "criado", Valor: req.Valor})
}
💻 Código de Exemplo 02 — main.go com Security Definitions e Registro do Swagger UI
package main
import (
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
_ "meuservico/docs" // gerado por `swag init`; registra a spec via init()
"meuservico/handlers"
)
// @title API de Pedidos
// @version 1.0
// @description Serviço de gerenciamento de pedidos com autenticação JWT.
// @host localhost:8080
// @BasePath /api/v1
// @securityDefinitions.apikey BearerAuth
// @in header
// @name Authorization
// @description Informe: Bearer {seu_token_jwt}
func main() {
r := gin.Default()
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
v1 := r.Group("/api/v1")
{
v1.GET("/pedidos/:id", handlers.ObterPedido)
v1.POST("/pedidos", handlers.CriarPedido)
}
r.Run(":8080")
}
// Fluxo de geração:
// 1. go install github.com/swaggo/swag/cmd/swag@latest
// 2. swag init -> gera docs/docs.go, docs/swagger.json, docs/swagger.yaml
// 3. go run main.go
// 4. abrir http://localhost:8080/swagger/index.html
💻 Código de Exemplo 03 — Validação de Sincronia da Documentação em CI
// check_swagger_sync.go
package main
import (
"bytes"
"log"
"os/exec"
)
// VerificarSwaggerSincronizado roda `swag init` de novo e compara a saída
// com o que está commitado em docs/. Usado como etapa de pipeline CI —
// se houver diff, alguém alterou rotas/DTOs sem regenerar a documentação.
func VerificarSwaggerSincronizado() error {
cmd := exec.Command("swag", "init", "--output", "docs")
if out, err := cmd.CombinedOutput(); err != nil {
return err
}
diff := exec.Command("git", "diff", "--exit-code", "docs/")
var stderr bytes.Buffer
diff.Stderr = &stderr
if err := diff.Run(); err != nil {
log.Println("documentação Swagger desatualizada:", stderr.String())
return err
}
log.Println("documentação Swagger 100% sincronizada com o código.")
return nil
}