Hướng Dẫn Xây Dựng API RESTful với Golang, Gin, Gorm và PostgreSQL
Bài viết này cung cấp một ví dụ chi tiết về dịch vụ API RESTful được xây dựng bằng Golang, sử dụng gin
để định tuyến, gorm
làm ORM, và PostgreSQL làm cơ sở dữ liệu. Ví dụ này bao gồm các tính năng của PostgreSQL như: tạo cơ sở dữ liệu và bảng, chèn và truy vấn dữ liệu, lập chỉ mục, hàm và thủ tục lưu trữ, trigger, views, CTEs, giao dịch, ràng buộc, và xử lý JSON.
1. Thiết Lập Dự Án
Giả sử bạn đã cài đặt PostgreSQL (để có cài đặt nhanh) và Golang cùng với go mod
. Hãy khởi tạo dự án:
bash
mkdir library-api
dcd library-api
go mod init library-api
Cấu trúc dự án
/library-api
|-- db.sql
|-- main.go
|-- go.mod
2. Cài Đặt Các Thư Viện Cần Thiết
Cài đặt các gói cần thiết:
bash
go get github.com/gin-gonic/gin
go get gorm.io/gorm
go get gorm.io/driver/postgres
3. Schematic PostgreSQL
Đây là tập lệnh SQL để tạo schema cho cơ sở dữ liệu:
sql
-- Tạo cơ sở dữ liệu thư viện.
CREATE DATABASE library;
-- Kết nối tới cơ sở dữ liệu thư viện.
\c library;
-- Tạo các bảng.
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL UNIQUE,
bio TEXT
);
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title VARCHAR(200) NOT NULL,
author_id INTEGER REFERENCES authors(id) ON DELETE CASCADE,
published_date DATE NOT NULL,
description TEXT,
details JSONB
);
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Tạo bảng ghi mượn, phân vùng theo năm.
CREATE TABLE borrow_logs (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
book_id INTEGER REFERENCES books(id),
borrowed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
returned_at TIMESTAMP
) PARTITION BY RANGE (borrowed_at);
CREATE TABLE borrow_logs_2023 PARTITION OF borrow_logs
FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');
CREATE TABLE borrow_logs_2024 PARTITION OF borrow_logs
FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');
-- Tạo chỉ mục để tìm kiếm nhanh hơn.
CREATE INDEX idx_books_published_date ON books (published_date);
CREATE INDEX idx_books_details ON books USING GIN (details);
-- Thêm view để lấy thông tin sách và tác giả.
CREATE VIEW book_author_view AS
SELECT books.id AS book_id, books.title, authors.name AS author_name
FROM books
JOIN authors ON books.author_id = authors.id;
4. Mã Golang
Dưới đây là ví dụ hoàn chỉnh về API RESTful sử dụng Gin và GORM:
go
package main
import (
"net/http"
"strconv"
"time"
"github.com/gin-gonic/gin"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type Author struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"not null;unique"`
Bio string
}
type Book struct {
ID uint `gorm:"primaryKey"`
Title string `gorm:"not null"`
AuthorID uint `gorm:"not null"`
PublishedDate time.Time `gorm:"not null"`
Details map[string]interface{} `gorm:"type:jsonb"`
}
// Các cấu trúc khác...
var db *gorm.DB
func initDB() {
dsn := "host=localhost user=postgres password=yourpassword dbname=library port=5432 sslmode=disable"
var err error
db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("không thể kết nối tới cơ sở dữ liệu")
}
// Tự động di chuyển các mô hình.
db.AutoMigrate(&Author{}, &Book{}, &User{}, &BorrowLog{})
}
func main() {
initDB()
r := gin.Default()
r.POST("/authors", createAuthor)
// Các route khác...
r.Run(":8080")
}
5. Chạy API
- Chạy tập lệnh SQL PostgreSQL để tạo bảng, chỉ mục, view, hàm và trigger.
- Khởi động máy chủ Golang bằng lệnh:
bash
go run main.go
Giờ đây, bạn đã có một API RESTful với Golang bao gồm nhiều tính năng của PostgreSQL, làm cho nó trở thành một ví dụ hoàn hảo để học hoặc phỏng vấn.
6. Thêm Tính Năng Mới
Chúng ta sẽ mở rộng ví dụ API RESTful bằng cách tích hợp các tính năng mở rộng khác của PostgreSQL như Views, CTEs, lập chỉ mục全文 văn bản và xử lý JSON. Tất cả những tính năng này sẽ được trình bày kèm theo các mã Golang tương ứng.
go
// Truy xuất View lịch sử mượn sách của người dùng:
func getUserBorrowHistory(c *gin.Context) {
var history []struct {
UserID uint `json:"user_id"`
UserName string `json:"user_name"`
BookTitle string `json:"book_title"`
BorrowedAt time.Time `json:"borrowed_at"`
ReturnedAt *time.Time `json:"returned_at,omitempty"`
}
if err := db.Raw("SELECT * FROM user_borrow_history WHERE user_id = ?", c.Param("user_id")).Scan(&history).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, history)
}
// Các hàm khác...
7. Tính Năng Nâng Cao Khác
Chúng ta có thể bổ sung thêm một số tính năng nâng cao như VACUUM, MVCC và Window Functions. Các tính năng này sẽ giúp nâng cao tối đa khả năng quản lý cơ sở dữ liệu và cải thiện hiệu suất truy vấn.
go
// Hàm thực hiện VACUUM.
func vacuumBooks(c *gin.Context) {
if err := db.Exec("VACUUM ANALYZE books").Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"status": "Vacuum đã được thực hiện thành công"})
}
// Các hàm khác...
Thông qua bài viết này, bạn sẽ nắm vững các kỹ thuật để xây dựng một API RESTful mạnh mẽ và hiệu quả.Maximize your learning about Golang, Gin, Gorm, và PostgreSQL để phát triển các ứng dụng web chất lượng cao.
source: viblo