---
title: "Como Criar uma API REST com Golang e Gin - Parte 4: Banco de Dados com GORM"
url: "https://golang.com.br/aprenda/api-rest-gin-parte4/"
markdown_url: "https://golang.com.br/aprenda/api-rest-gin-parte4.MD"
description: "Parte 4 (final): conecte a API Golang/Gin ao PostgreSQL usando GORM, implemente migrations e prepare para deploy com Docker."
date: "2026-04-30"
author: ""
---

# Como Criar uma API REST com Golang e Gin - Parte 4: Banco de Dados com GORM

Parte 4 (final): conecte a API Golang/Gin ao PostgreSQL usando GORM, implemente migrations e prepare para deploy com Docker.


# Como Criar uma API REST com Golang e Gin - Parte 4: Banco de Dados com GORM

Na parte final da série, vamos conectar nossa API ao **PostgreSQL** usando **GORM** (Object Relational Mapping para Go).

## Instalando o GORM e Driver PostgreSQL

```bash
go get -u gorm.io/gorm
go get -u gorm.io/driver/postgres
```

## Configurando a Conexão

Crie um arquivo `db/db.go`:

```go
package db

import (
    "fmt"
    "log"
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

var DB *gorm.DB

func Connect() {
    dsn := "host=localhost user=postgres password=suasenha dbname=booksdb port=5432 sslmode=disable"
    
    var err error
    DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
    
    if err != nil {
        log.Fatal("Falha ao conectar ao banco:", err)
    }
    
    fmt.Println("Conectado ao PostgreSQL!")
}
```

## Modelo GORM

Atualize `Book` para usar tags GORM:

```go
type Book struct {
    ID     uint    `json:"id" gorm:"primaryKey"`
    Title  string  `json:"title" binding:"required,min=3,max=100" gorm:"type:varchar(100);not null"`
    Author string  `json:"author" binding:"required" gorm:"type:varchar(100);not null"`
    Price  float64 `json:"price" binding:"required,gt=0" gorm:"type:decimal(10,2);not null"`
}
```

## Migrations Automáticas

No `main.go`:

```go
package main

import (
    "github.com/gin-gonic/gin"
    "github.com/seuusuario/golang-api-gin/db"
    "github.com/seuusuario/golang-api-gin/models"
)

func main() {
    // Conecta ao banco
    db.Connect()
    
    // Executa migrations (cria tabelas se não existirem)
    db.DB.AutoMigrate(&models.Book{})
    
    r := gin.Default()
    
    // Rotas (iguais às partes anteriores, mas agora usam o banco)
    books := r.Group("/books")
    {
        books.GET("", getBooks)
        books.GET("/:id", getBook)
        books.POST("", createBook)
        books.PUT("/:id", updateBook)
        books.DELETE("/:id", deleteBook)
    }
    
    r.Run(":8080")
}
```

## Handlers com GORM

```go
func getBooks(c *gin.Context) {
    var books []models.Book
    db.DB.Find(&books)
    c.JSON(200, books)
}

func getBook(c *gin.Context) {
    id := c.Param("id")
    var book models.Book
    result := db.DB.First(&book, id)
    
    if result.Error != nil {
        c.JSON(404, gin.H{"error": "Livro não encontrado"})
        return
    }
    
    c.JSON(200, book)
}

func createBook(c *gin.Context) {
    var newBook models.Book
    if err := c.ShouldBindJSON(&newBook); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    
    db.DB.Create(&newBook)
    c.JSON(201, newBook)
}

func updateBook(c *gin.Context) {
    id := c.Param("id")
    var updatedBook models.Book
    
    if err := c.ShouldBindJSON(&updatedBook); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    
    var book models.Book
    db.DB.First(&book, id)
    
    db.DB.Model(&book).Updates(updatedBook)
    c.JSON(200, book)
}

func deleteBook(c *gin.Context) {
    id := c.Param("id")
    db.DB.Delete(&models.Book{}, id)
    c.Status(204)
}
```

## Dockerizando a Aplicação

Crie um `Dockerfile`:

```dockerfile
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o api main.go

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root
COPY --from=builder /app/api .
EXPOSE 8080
CMD ["./api"]
```

Crie `docker-compose.yml`:

```yaml
version: '3.8'
services:
  db:
    image: postgres:15
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: suasenha
      POSTGRES_DB: booksdb
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data

  api:
    build: .
    ports:
      - "8080:8080"
    environment:
      DB_HOST: db
      DB_USER: postgres
      DB_PASSWORD: suasenha
      DB_NAME: booksdb
      DB_PORT: 5432
    depends_on:
      - db

volumes:
  postgres_data:
```

## Executando com Docker

```bash
docker-compose up --build
```

## Conclusão da Série

Parabéns! Você criou uma API REST completa com:
✅ Framework Gin para rotas  
✅ Validação de dados  
✅ Middleware de logging e auth  
✅ Banco PostgreSQL com GORM  
✅ Docker para deploy  

## Próximos Passos (Além da Série)

- Adicionar **testes automatizados** (testing package)
- Implementar **JWT authentication** real
- Configurar **CI/CD** com GitHub Actions
- Adicionar **logs estruturados** (zap logger)
- Documentação com **Swagger** (swaggo)

---

*Série completa! Compartilhe no [Twitter](https://twitter.com/golangbr) e deixe seu feedback no [Telegram](https://t.me/golangbr)!*
