Implementando Arquitetura MVC e Persistência de Dados com Go, Gin e GORM

A adoção de uma arquitetura bem definida é essencial para o desenvolvimento de aplicações robustas e escaláveis. Em Go, o padrão MVC (Model-View-Cotnroller) pode ser implementado de forma eficiente utilizando o framework web Gin para o roteamento e o GORM como ferramenta de ORM (Object-Relational Mapping) para interação com bancos de dados relacionais.

Para iniciar o projeto, é necessário instalar as dependências fundamentais via terminal:

go get -u github.com/gin-gonic/gin
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql

A organização sugerida para este projeto separa as responsabilidades em camadas distintas, facilitando a manutenção e os testes unitários:

- main.go
- controllers/
 - usuario_controller.go
- models/
 - usuario.go
- services/
 - usuario_service.go
- repositories/
 - usuario_repository.go

1. Definição do Modelo

No diretório models/usuario.go, definimos a estrutura de dados que representa a tabela no banco de dados.

package models

type Usuario struct {
   ID       uint   `gorm:"primaryKey;column:id" json:"id"`
   Nome     string `gorm:"column:nome_usuario" json:"nome"`
   Email    string `gorm:"column:email" json:"email"`
   Endereco string `gorm:"column:endereco" json:"endereco"`
}

2. Camada de Repositório

A camada de repositório isola o acesso aos dados. Em repositories/usuario_repository.go, implementamos as opperações de consulta utilizando o GORM.

package repositories

import (
   "projeto_mvc/models"
   "gorm.io/gorm"
)

type UsuarioRepo struct {
   db *gorm.DB
}

func NovoUsuarioRepo(db *gorm.DB) *UsuarioRepo {
   return &UsuarioRepo{db: db}
}

func (r *UsuarioRepo) BuscarTodos() ([]models.Usuario, error) {
   var usuarios []models.Usuario
   if err := r.db.Find(&usuarios).Error; err != nil {
       return nil, err
   }
   return usuarios, nil
}

3. Camada de Serviço

A camada de serviço em services/usuario_service.go contém a lógica de negócio e atua como ponte entre o controlador e o repositório.

package services

import (
   "projeto_mvc/models"
   "projeto_mvc/repositories"
)

type UsuarioService struct {
   repo *repositories.UsuarioRepo
}

func NovoUsuarioService(r *repositories.UsuarioRepo) *UsuarioService {
   return &UsuarioService{repo: r}
}

func (s *UsuarioService) ListarUsuarios() ([]models.Usuario, error) {
   // Aqui poderiam ser adicionadas regras de negócio adicionais
   return s.repo.BuscarTodos()
}

4. Camada de Controle

O controlador em controllers/usuario_controller.go gerencia as requisições HTTP, processa a entrada e retorna a resposta formatada ao cliente.

package controllers

import (
   "net/http"
   "projeto_mvc/services"
   "github.com/gin-gonic/gin"
)

type UsuarioHandler struct {
   service *services.UsuarioService
}

func NovoUsuarioHandler(s *services.UsuarioService) *UsuarioHandler {
   return &UsuarioHandler{service: s}
}

func (h *UsuarioHandler) ListarTodos(c *gin.Context) {
   resultado, err := h.service.ListarUsuarios()
   if err != nil {
       c.JSON(http.StatusInternalServerError, gin.H{"erro": "Falha ao recuperar dados"})
       return
   }
   c.JSON(http.StatusOK, resultado)
}

5. Ponto de Entrada (Main)

O arquivo main.go é responsável por configurar a conexão com o banco de dados, instanciar as dependências e definir as rotas da API.

package main

import (
   "log"
   "github.com/gin-gonic/gin"
   "gorm.io/driver/mysql"
   "gorm.io/gorm"
   "projeto_mvc/controllers"
   "projeto_mvc/repositories"
   "projeto_mvc/services"
)

func configurarDB() *gorm.DB {
   dsn := "usuario:senha@tcp(127.0.0.1:3306)/nome_banco?charset=utf8mb4&parseTime=True&loc=Local"
   db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
   if err != nil {
       log.Fatal("Erro ao conectar no banco de dados:", err)
   }
   return db
}

func main() {
   router := gin.Default()
   database := configurarDB()

   // Injeção de dependências
   repo := repositories.NovoUsuarioRepo(database)
   svc := services.NovoUsuarioService(repo)
   handler := controllers.NovoUsuarioHandler(svc)

   // Definição de rotas
   v1 := router.Group("/api/v1")
   {
       v1.GET("/usuarios", handler.ListarTodos)
   }

   router.Run(":8080")
}

Ao estruturar a aplicação desta forma, garantimos que cada componente tenha uma responsabilidade única (Single Responsibility Principle). O repositório lida exclusivamente com o banco de dados, o serviço com as regras de negócio e o controlador com a interface de comunicação HTTP, resultando em um código mais limpo e modular.

Tags: go GORM Gin-Gonic MVC MySQL

Publicado em 7-30 07:39