Como Documentar Sua API em Go

Sumário

Hoje vou escrever um post técnico sobre documentação de APIs em Go. Espero que seja útil!

Primeiro, vamos criar uma API CRUD simples usando Go e o framework Gin. Vamos começar!

package main

import (
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
)

type User struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

var users = []User{
	{ID: 1, Name: "John"},
	{ID: 2, Name: "Doe"},
}

func main() {
	r := gin.Default()

	// Change to default is /api/v1
	api := r.RouterGroup.Group("/api/v1")
	{
		api.GET("/users", getUsers)

		api.GET("/users/:id", getUser)

		api.POST("/users", createUser)

		api.PUT("/users", editUser)

		api.DELETE("/users/:id", removeUser)
	}

	r.Run(":8080")
}

func getUsers(c *gin.Context) {
	c.JSON(http.StatusOK, users)
}

func getUser(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))
	userFound, _ := findUserByID(users, id)
	c.JSON(http.StatusOK, userFound)
}

func createUser(c *gin.Context) {
	var user User
	c.BindJSON(&user)
	users = append(users, user)
	c.JSON(http.StatusCreated, user)
}

func editUser(c *gin.Context) {
	var user User
	c.BindJSON(&user)
	putUser(users, user)
	c.JSON(http.StatusOK, user)
}

func removeUser(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))
	deleteUserByID(users, id)
	c.JSON(http.StatusOK, nil)
}

func findUserByID(users []User, id int) (*User, bool) {
	for _, user := range users {
		if user.ID == id {
			return &user, true
		}
	}
	return nil, false
}

func deleteUserByID(users []User, id int) []User {
	newUsers := []User{}
	for _, user := range users {
		if user.ID != id {
			newUsers = append(newUsers, user)
		}
	}
	return newUsers
}

func putUser(users []User, newUser User) []User {
	for i := range users {
		if users[i].ID == newUser.ID {
			// Update the existing user
			users[i] = newUser
			return users
		}
	}
	// Add new user if not found
	return append(users, newUser)
}

Agora que temos uma API CRUD simples em Go, vamos documentá-la.

Observação: neste exemplo, não usei a melhor abordagem para um CRUD. Defini uma struct User para representar um usuário e usei um slice para armazenar os usuários. Em um projeto real, você deve usar um banco de dados para armazenar os dados. Além disso, embora eu tenha usado funções básicas para manipular os dados, o recomendado em código de produção é seguir o padrão repository.

Esclarecido isso, vamos criar nossa documentação.

Primeiro, vamos criar um Makefile para facilitar o gerenciamento da aplicação.

run:
    go run main.go

build-swagger:
	@go run github.com/swaggo/swag/cmd/swag@latest init -g main.go -o docs

Agora, precisamos instalar algumas dependências para usar o Swag.

    go get -u github.com/swaggo/gin-swagger
    go get -u github.com/swaggo/files

Agora, preciso adicionar algumas descrições usando comentários no código da função main.

// @BasePath /api/v1

// PingExample godoc
// @Summary ping example
// @Schemes
// @Description do ping
func main...

Precisamos adicionar uma rota para servir a documentação do Swagger.

r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))

Agora, precisamos rodar um comando para gerar a documentação.

make build-swagger

Com todas as configurações do Swag prontas, podemos rodar a aplicação e acessar a documentação no navegador.

make run

Agora, acesse a URL http://localhost:8080/swagger/index.html para ver a documentação.

Abaixo está um exemplo de como documentar um CRUD:

GET USERS:

// @BasePath /
// ShowAccount 	 godoc
// @Summary      Show a Users list
// @Description  get users
// @Tags         getUsers
// @Accept       json
// @Produce      json
// @Router       /users  [get]

GET USER:

// @BasePath /
// ShowAccount 	 godoc
// @Summary      Show a Users list
// @Description  get users
// @Tags         getUsers
// @Accept       json
// @Produce      json
// @Param        id         path      string  true  "ID"
// @Router       /users/{id}  [get]

POST:

// @BasePath /
// ShowAccount 	 godoc
// @Summary      Create a User
// @Description  create users
// @Tags         createUser
// @Accept       json
// @Produce      json
// @Param user body User true "User to create"
// @Router 		/users [post]

PUT:

// @BasePath /
// ShowAccount 	 godoc
// @Summary      Edit a User
// @Description  edit users
// @Tags         editUser
// @Accept       json
// @Produce      json
// @Param user body User true "User to edit"
// @Router 		/users [put]

DELETE:

// @BasePath /
// ShowAccount 	 godoc
// @Summary      Remove a Users list
// @Description  delete user
// @Tags         removeUser
// @Accept       json
// @Produce      json
// @Param        id         path      string  true  "ID"
// @Router       /users/{id}  [delete]

Com esses comentários em cada função, podemos gerar a documentação com o Swag.

O resultado é:

Exemplo do Swagger

Você pode ver o projeto no repositório.

Conclusão

Neste artigo, aprendemos a documentar uma API em Go usando o Swag. Começamos criando uma API CRUD simples em Go e depois a documentamos com o Swag. Também aprendemos a gerar a documentação e a visualizá-la no navegador.

O Swag é uma ferramenta poderosa que ajuda a documentar suas APIs em Go com facilidade.

Espero que este artigo tenha sido útil. Se tiver dúvidas ou sugestões, fique à vontade para me mandar uma mensagem nas minhas redes sociais.

Obrigado pela leitura!