Conteúdo
Golang, também conhecida como Go, é uma linguagem de programação muito requisitada no mercado, com grande potencial em diversas aplicações. Quando utilizada em conjunto com frameworks como Gin, Revel ou gorilla/mux, é possível desenvolver APIs de forma eficiente. Neste guia, você aprenderá a criar uma API CRUD utilizando Golang, com o framework Gin para manipulação das requisições HTTP, e MongoDB como banco de dados.
Leia também: Vale a pena aprender Golang hoje?
Configuração inicial
Se ainda não possui o Go instalado em seu sistema, faça o download e instale-o. Após isso, crie um diretório para o projeto e inicialize um módulo Go dentro dele. Para isso, execute os seguintes comandos no terminal:
go mod init nome_do_modulo
Esse comando criará um arquivo go.mod
com as informações do módulo, que servirá de base para os pacotes personalizados. Agora, instale o framework Gin para criar e gerenciar as rotas da API:
go get github.com/gin-gonic/gin
Em seguida, instale o driver do MongoDB para que possa armazenar e gerenciar os dados no banco de dados:
go get go.mongodb.org/mongo-driver/mongo
Conectando o Go ao MongoDB
Para conectar o Go ao MongoDB, você precisará da URL de conexão. Se estiver utilizando o MongoDB localmente, sua URI será semelhante a esta:
Mongo_URL := "mongodb://127.0.0.1:27017"
Crie uma pasta chamada databases
no diretório raiz do projeto e adicione um arquivo database.go
para gerenciar a conexão com o banco de dados. O código para a conexão será assim:
package database
import (
"context"
"log"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func ConnectDB() *mongo.Client {
client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://127.0.0.1:27017"))
if err != nil {
log.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
err = client.Connect(ctx)
if err != nil {
log.Fatal(err)
}
log.Println("Conectado ao MongoDB")
return client
}
Recomenda-se usar arquivos .env
para armazenar variáveis sensíveis, como a string de conexão do banco de dados.
Manipulando coleções do MongoDB
As coleções no MongoDB são responsáveis por armazenar os documentos. Para facilitar o acesso a essas coleções, crie uma pasta Collection
e dentro dela um arquivo getCollection.go
com o seguinte código:
package getcollection
import "go.mongodb.org/mongo-driver/mongo"
func GetCollection(client *mongo.Client, collectionName string) *mongo.Collection {
return client.Database("meuAppGo").Collection(collectionName)
}
Essa função recupera a coleção especificada, neste caso, da base de dados meuAppGo
.
Definindo o modelo de dados
Crie uma pasta model
para organizar o modelo de dados. Dentro dela, crie um arquivo model.go
que definirá o modelo de post, com título e conteúdo:
package model
import "go.mongodb.org/mongo-driver/bson/primitive"
type Post struct {
ID primitive.ObjectID `bson:"_id,omitempty"`
Title string `bson:"title"`
Article string `bson:"article"`
}
Criando os endpoints CRUD
Agora, é hora de criar os endpoints para manipular os dados. Para isso, crie uma pasta chamada routes
e, dentro dela, arquivos para cada ação: create.go
, read.go
, update.go
e delete.go
.
Endpoint POST (Criar)
O endpoint para criar novos posts ficará assim:
package routes
import (
"context"
"net/http"
"time"
"log"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson/primitive"
"CRUD_API/databases"
"CRUD_API/model"
"CRUD_API/Collection"
)
func CreatePost(c *gin.Context) {
var DB = databases.ConnectDB()
var postCollection = Collection.GetCollection(DB, "Posts")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
var post model.Post
if err := c.BindJSON(&post); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"message": err.Error()})
return
}
post.ID = primitive.NewObjectID()
_, err := postCollection.InsertOne(ctx, post)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{"message": "Post criado com sucesso!"})
}
Endpoint GET (Ler)
Para ler um post específico pelo ID:
package routes
import (
"context"
"net/http"
"time"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"CRUD_API/databases"
"CRUD_API/model"
"CRUD_API/Collection"
)
func ReadOnePost(c *gin.Context) {
var DB = databases.ConnectDB()
var postCollection = Collection.GetCollection(DB, "Posts")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
postId := c.Param("postId")
objId, _ := primitive.ObjectIDFromHex(postId)
var post model.Post
err := postCollection.FindOne(ctx, bson.M{"_id": objId}).Decode(&post)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": post})
}
Endpoint PUT (Atualizar)
Para atualizar um post:
package routes
import (
"context"
"net/http"
"time"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"CRUD_API/databases"
"CRUD_API/model"
"CRUD_API/Collection"
)
func UpdatePost(c *gin.Context) {
var DB = databases.ConnectDB()
var postCollection = Collection.GetCollection(DB, "Posts")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
postId := c.Param("postId")
objId, _ := primitive.ObjectIDFromHex(postId)
var post model.Post
if err := c.BindJSON(&post); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"message": err.Error()})
return
}
update := bson.M{"title": post.Title, "article": post.Article}
_, err := postCollection.UpdateOne(ctx, bson.M{"_id": objId}, bson.M{"$set": update})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Post atualizado com sucesso!"})
}
Endpoint DELETE (Excluir)
Para remover um post pelo ID:
package routes
import (
"context"
"net/http"
"time"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"CRUD_API/databases"
"CRUD_API/Collection"
)
func DeletePost(c *gin.Context) {
var DB = databases.ConnectDB()
var postCollection = Collection.GetCollection(DB, "Posts")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
postId := c.Param("postId")
objId, _ := primitive.ObjectIDFromHex(postId)
_, err := postCollection.DeleteOne(ctx, bson.M{"_id": objId})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Post deletado com sucesso!"})
}
Executando o projeto
No arquivo principal main.go
, importe as rotas e configure o roteador:
package main
import (
"CRUD_API/routes"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.POST("/create", routes.CreatePost)
router.GET("/read/:postId", routes.ReadOnePost)
router.PUT("/update/:postId", routes.UpdatePost)
router.DELETE("/delete/:postId", routes.DeletePost)
router.Run(":3000")
}
Conclusão
Você criou uma API CRUD completa com Golang, Gin e MongoDB. Essa estrutura é apenas o início para projetos mais robustos e escaláveis.
Leia também: Como criar um ambiente de desenvolvimento PHP no Linux