---
title: "Como Criar uma API REST com Golang e Gin - Parte 3: Validação e Middleware"
url: "https://golang.com.br/aprenda/api-rest-gin-parte3/"
markdown_url: "https://golang.com.br/aprenda/api-rest-gin-parte3.MD"
description: "Parte 3 da série: adicione validação de dados, middleware de logging/autenticação e tratamento de erros estruturado na API Golang com Gin."
date: "2026-04-30"
author: ""
---

# Como Criar uma API REST com Golang e Gin - Parte 3: Validação e Middleware

Parte 3 da série: adicione validação de dados, middleware de logging/autenticação e tratamento de erros estruturado na API Golang com Gin.


# Como Criar uma API REST com Golang e Gin - Parte 3: Validação e Middleware

Na Parte 2 criamos o CRUD completo. Agora vamos adicionar **validação**, **middleware** e **tratamento de erros**.

## Validação com Struct Tags

O Gin usa a biblioteca `validator` para validar dados. Adicione tags nas structs:

```go
type Book struct {
    ID     string  `json:"id" binding:"required"`
    Title  string  `json:"title" binding:"required,min=3,max=100"`
    Author string  `json:"author" binding:"required"`
    Price  float64 `json:"price" binding:"required,gt=0"`
}
```

Agora o `ShouldBindJSON` valida automaticamente:

```go
func createBook(c *gin.Context) {
    var newBook Book
    if err := c.ShouldBindJSON(&newBook); err != nil {
        c.JSON(400, gin.H{
            "error":   "Dados inválidos",
            "details": err.Error(),
        })
        return
    }
    books = append(books, newBook)
    c.JSON(201, newBook)
}
```

## Criando Middleware

### Middleware de Logging

```go
func LoggerMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        start := time.Now()
        
        // Processa a requisição
        c.Next()
        
        // Após a requisição
        latency := time.Since(start)
        gin.DefaultWriter.Write([]byte(fmt.Sprintf(
            "[%s] %s %s %v\n",
            time.Now().Format("2006-01-02 15:04:05"),
            c.Request.Method,
            c.Request.URL.Path,
            latency,
        )))
    }
}
```

### Middleware de Autenticação (API Key)

```go
func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        apiKey := c.GetHeader("X-API-Key")
        if apiKey != "meu-secret-key" {
            c.AbortWithStatusJSON(401, gin.H{
                "error": "Não autorizado",
            })
            return
        }
        c.Next()
    }
}
```

## Aplicando os Middleware

```go
func main() {
    r := gin.Default()
    
    // Middleware global
    r.Use(LoggerMiddleware())
    
    // Grupo de rotas protegidas
    books := r.Group("/books")
    books.Use(AuthMiddleware())
    {
        books.GET("", getBooks)
        books.GET("/:id", getBook)
        books.POST("", createBook)
        books.PUT("/:id", updateBook)
        books.DELETE("/:id", deleteBook)
    }
    
    r.Run(":8080")
}
```

## Tratamento de Erros Estruturado

Crie um helper para erros:

```go
type AppError struct {
    Message string `json:"message"`
    Code    int    `json:"code"`
}

func NewAppError(message string, code int) *AppError {
    return &AppError{Message: message, Code: code}
}

func (e *AppError) Error() string {
    return e.Message
}
```

Uso nos handlers:

```go
func getBook(c *gin.Context) {
    id := c.Param("id")
    for _, book := range books {
        if book.ID == id {
            c.JSON(200, book)
            return
        }
    }
    c.JSON(404, AppError{Message: "Livro não encontrado", Code: 404})
}
```

## Testando

```bash
# Listar livros (precisa do header X-API-Key)
curl -H "X-API-Key: meu-secret-key" http://localhost:8080/books

# Criar livro com dados inválidos
curl -X POST http://localhost:8080/books \
  -H "X-API-Key: meu-secret-key" \
  -H "Content-Type: application/json" \
  -d '{"title":"AB","price":-10}'

# Resposta de erro:
# {"error":"Dados inválidos","details":"Key: 'Book.Title' Error:Field validation for 'Title' failed on the 'min' tag..."}
```

## Próximos Passos

Na **Parte 4** (final), vamos:
- Conectar ao **PostgreSQL** com GORM
- Implementar migrations
- Deploy com Docker

👉 [Parte 4: Banco de Dados com GORM](/aprenda/api-rest-gin-parte4/)

---

*Gostou deste tutorial? Compartilhe no [Twitter](https://twitter.com/golangbr) e deixe seu feedback no [Telegram](https://t.me/golangbr)!*
