In the previous blog, we introduced how to build a simple microservice with Go. Now, we’ll take it a step further by adding database integration, which is a crucial part of most microservice architectures. By the end of this post, you’ll learn how to connect a Go microservice to a database (PostgreSQL, in this case) using GORM, a popular ORM library for Go, perform CRUD operations, and structure your Go code to manage database logic efficiently.
Why Database Integration Matters in Microservices
Microservices often require persistent storage to manage data independently. Each microservice may have its own database to ensure loose coupling. This setup allows independent scaling, fault isolation, and decentralized data management. By using Go, which provides excellent support for database interaction through packages like database/sql
, we can make our microservices both lightweight and efficient.
Choosing a Database
For this blog, we’ll integrate PostgreSQL, an open-source, powerful relational database. However, the same principles apply if you choose another database like MySQL, MongoDB, or SQLite. PostgreSQL is chosen due to its robustness and wide community support. We’ll walk through setting up GORM, connecting to a PostgreSQL database, and performing basic CRUD (Create, Read, Update, Delete) operations.
Why GORM?
GORM simplifies database interactions by allowing you to define Go structures that map to database tables. It offers features like:
Automatic table creation based on Go structs.
Easy migrations for schema updates.
Comprehensive CRUD support with rich querying methods.
Setting Up PostgreSQL and GORM
First, we need to install PostgreSQL and GORM.
Install PostgreSQL:
If you don’t have PostgreSQL installed, download and install it from the official website.
Create a new database for the microservice
psql -U postgres CREATE DATABASE go_microservice_db;
Install GORM: Add GORM and the PostgreSQL driver to your project:
go get -u gorm.io/gorm go get -u gorm.io/driver/postgres
Database Configuration and Initialization
Let’s modify our project structure slightly to support database interactions.
Create a database connection helper in the
internal/
directory.File:
internal/db/db.go
package db import ( "gorm.io/driver/postgres" "gorm.io/gorm" "log" ) var DB *gorm.DB func Init() { dsn := "host=localhost user=postgres password=yourpassword dbname=go_microservice_db port=5432 sslmode=disable" var err error DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{}) if err != nil { log.Fatal("Failed to connect to database:", err) } log.Println("Database connected") }
This code initializes the connection to the PostgreSQL database using GORM. Replace
yourpassword
with your PostgreSQL password.Create a model that represents the data we will store in the database.
File:
internal/models/user.go
package models import "gorm.io/gorm" type User struct { gorm.Model Name string `json:"name"` Email string `json:"email"` }
This struct defines a
User
model with fields forName
andEmail
. GORM will automatically map this struct to ausers
table in PostgreSQL.CRUD Operations
Now that we have a database connection and model, let’s write the microservice to handle CRUD operations.
Migrate the schema: GORM can automatically create the
users
table for us. Call theAutoMigrate
function when the service starts.File:
cmd/service1/main.go
package main import ( "go-microservice/internal/db" "go-microservice/internal/models" "log" "net/http" "gorm.io/gorm" "encoding/json" "io/ioutil" ) func createUserHandler(w http.ResponseWriter, r *http.Request) { body, _ := ioutil.ReadAll(r.Body) var user models.User json.Unmarshal(body, &user) db.DB.Create(&user) w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(user) } func listUsersHandler(w http.ResponseWriter, r *http.Request) { var users []models.User db.DB.Find(&users) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(users) } func main() { db.Init() // Migrate the schema db.DB.AutoMigrate(&models.User{}) http.HandleFunc("/users", createUserHandler) http.HandleFunc("/users/list", listUsersHandler) log.Println("Server running on port 8080") http.ListenAndServe(":8080", nil) }
Running the service: When you run the service, it will connect to PostgreSQL, create the
users
table, and expose two routes:POST
/users
: to create a new user by sending a JSON payload like{ "name": "John Doe", "email": "
john@example.com
" }
.GET
/users/list
: to fetch a list of all users.
Testing the CRUD endpoints:
Use
curl
to test the endpoints:# Create a new user curl -X POST -d '{"name":"John Doe", "email":"john@example.com"}' -H "Content-Type: application/json" http://localhost:8080/users # Fetch all users curl http://localhost:8080/users/list
Conclusion
In this blog post, we integrated PostgreSQL into our Go microservice using GORM. We demonstrated how to:
Set up a PostgreSQL database.
Create a database connection with GORM.
Define a model and perform basic CRUD operations.
In the next post, we’ll explore inter-service communication using HTTP and gRPC, diving deeper into how microservices can communicate with each other.