Ứng dụng Go đầu tiên của bạn – Xây dựng RESTful API sử dụng Gin framework và GORM ORM, kết nối với MySQL database.
- Tính năng
- Công nghệ sử dụng
- Cấu trúc thư mục
- Yêu cầu hệ thống
- Cài đặt
- Cấu hình Database
- Chạy ứng dụng
- Chạy bằng Docker
- Môi trường Staging/Production
- Môi trường Development (Docker)
- API Endpoints
- Ví dụ sử dụng
- ✅ RESTful API với Gin Framework
- ✅ ORM với GORM (MySQL)
- ✅ Auto Migration Database
- ✅ Middleware Logger tùy chỉnh
- ✅ Cấu trúc MVC rõ ràng
- ✅ Hot Reload trong môi trường development
- ✅ CRUD operations cho User
- ✅ Chuẩn hóa API response (success/statusCode/message/…)
- ✅ Hash & xác thực password bằng bcrypt + rule mạnh (hoa/thường/số/ký tự đặc biệt)
- Go 1.25.1
- Gin v1.11.0 – HTTP web framework
- GORM v1.31.0 – ORM library
- MySQL – Database
- Air – Hot reload tool (development)
GoFirstApp/
├── main.go # Entry point của ứng dụng
├── go.mod # Dependencies management
├── go.sum # Dependencies checksum
├── dev.ps1 # Script chạy dev server (PowerShell)
├── Makefile # Build & run tasks
├── .air.toml # Cấu hình hot reload
├── README.md # Tài liệu dự án
│
├── controllers/ # Business logic
│ └── userController.go # User CRUD operations
│
├── database/ # Database setup
│ └── db.go # Database connection & migration
│
├── middleware/ # Custom middleware
│ └── logger.go # Request logging middleware
│
├── models/ # Data models
│ └── user.go # User model (struct)
│
├── routes/ # Route definitions
│ ├── routes.go # Main router setup
│ └── userRoutes.go # User routes
│
└── tmp/ # Build artifacts (gitignore)
└── main.exe # Compiled binary
- Go 1.25.1 hoặc cao hơn
- MySQL 8.0 hoặc cao hơn
- Git (optional)
git clone <repository-url>
cd GoFirstApp
go mod download
go install github.com/air-verse/air@latest
docker run --name mysql-server -e MYSQL_ROOT_PASSWORD=rootpass -e MYSQL_DATABASE=mydb -e MYSQL_USER=myuser -e MYSQL_PASSWORD=mypass -p 3306:3306 -d mysql:8.0
- Connection type: MySQL
- Server name:
- Nếu bạn kết nối từ máy host (Windows/Linux) → điền localhost hoặc 127.0.0.1
- Nếu bạn kết nối từ một container khác trong cùng docker-compose → điền mysql-server (tên service/container).
- Authentication type: Password
- User name: myuser
- Password: mypass
- Database name: mydb
- Port: 3306 (mặc định)
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'myuser'@'localhost' IDENTIFIED BY 'mypass';
GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'localhost';
FLUSH PRIVILEGES;
Mở file database/db.go và chỉnh sửa DSN connection string:
dsn := "myuser:mypass@tcp(127.0.0.1:3306)/mydb?charset=utf8mb4&parseTime=True&loc=Local"
// ^^^^^^ ^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^
// user pass host:port database
go run main.go
# Cách 1: Dùng script PowerShell
.\dev.ps1
# Cách 2: Dùng Makefile (nếu đã cài Make)
make dev
# Cách 3: Dùng Air trực tiếp
go run github.com/air-verse/air@latest
# Build
go build -o tmp/main.exe .
# Run
.\tmp\main.exe
Server sẽ chạy tại: http://localhost:8080
- Tạo file
.envở thư mục gốc với giá trị ví dụ:
# App
APP_PORT=8080
# MySQL
DB_HOST=db
DB_PORT=3306
DB_NAME=mydb
DB_USER=myuser
DB_PASS=mypass
- Khởi chạy docker-compose:
docker compose up -d --build
- Truy cập API:
http://localhost:8080
Ghi chú:
- Service
dbdùngmysql:8.0và map cổng3306:3306cho host. - Ứng dụng chạy bằng binary đã build trong image (không mount source vào container) nhằm đảm bảo môi trường chạy ổn định.
- Biến
DB_HOSTmặc định được đặt làdbđể app kết nối MySQL nội bộ qua network của compose.
Từ nay ứng dụng hỗ trợ cấu hình đa môi trường qua biến APP_ENV và các file .env.*.
- App đọc
APP_ENVvà tìm file.env.<APP_ENV>trước, nếu không tồn tại sẽ fallback.env. - Ví dụ:
APP_ENV=staging→ ưu tiên.env.staging.
- Tạo file môi trường dựa trên mẫu:
copy .env.staging.example .env.staging # Windows PowerShell/cmd
# hoặc
cp .env.staging.example .env.staging # Linux/macOS
- Khởi chạy môi trường staging:
make staging-up
# Dừng và xóa: make staging-down
- App sẽ chạy tại
http://localhost:8081 - MySQL staging sẽ map
3307:3306để không xung đột với dev.
- Tạo file
.env.production(không commit) dựa trên mẫu:
copy .env.production.example .env.production
- Chạy production (app-only, không kèm MySQL nội bộ):
make prod-up # build & run image với APP_ENV=production
# Dừng: make prod-down
Ghi chú Production:
- Sử dụng DB managed (RDS/Cloud SQL, v.v.). Thiết lập
DB_HOST,DB_USER,DB_PASS,DB_NAMEtrong.env.production. - Image build tối giản từ Dockerfile multi-stage, chạy user không phải root.
Sử dụng docker-compose.dev.yml để chạy môi trường dev có hot reload (Air).
- Tạo file môi trường:
copy .env.development.example .env.development # Windows
# hoặc
cp .env.development.example .env.development # Linux/macOS
- Khởi chạy dev bằng Docker:
make docker-dev-up
# Dừng/xoá: make docker-dev-down
Ghi chú:
- App map cổng
8082:8080, MySQL dev map3308:3306để tránh xung đột. - Service
appdùng imagegolang:1.22, bind-mount code./:/srcvà chạyairđể hot reload.
| Method | Endpoint | Description | Request Body / Query |
|---|---|---|---|
| POST | /users | Tạo user mới | {"name":"...", "email":"...", "password":"..."} |
| GET | /users | Lấy danh sách users (hỗ trợ page, limit) |
?page=1&limit=10 (optional) |
| POST | /auth/login | Đăng nhập, nhận JWT | {"email":"...", "password":"..."} |
Tham số phân trang (GET /users):
page(mặc định1, nhỏ nhất1)limit(mặc định10, tối đa100)- Response trả về thêm khối
paginationgồmpage,limit,totalItems,totalPages.
Tất cả API đều trả JSON với envelope sau:
Success
{
"success": true,
"statusCode": 200,
"message": "Action description",
"data": {},
"pagination": {},
"metadata": {}
}
pagination & metadata chỉ xuất hiện khi cần.
Error
{
"success": false,
"statusCode": 400,
"message": "Validation failed",
"errors": [
{
"field": "password",
"message": "Password must be at least 8 characters",
"code": "PASSWORD_TOO_SHORT"
}
],
"metadata": {}
}
errors luôn là mảng để hỗ trợ nhiều lỗi cùng lúc.
User Model:
{
"success": true,
"statusCode": 200,
"message": "User created successfully",
"data": {
"id": 1,
"name": "Alice",
"email": "[email protected]"
}
}
PowerShell:
curl.exe -X POST http://localhost:8080/users `
-H "Content-Type: application/json" `
-d '{\"name\":\"Alice\", \"email\":\"[email protected]\"}'
Bash/Linux:
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"name":"Alice", "email":"[email protected]"}'
Response:
{
"id": 1,
"name": "Alice",
"email": "[email protected]"
}
PowerShell:
curl.exe http://localhost:8080/users
Response:
{
"success": true,
"statusCode": 200,
"message": "Users retrieved successfully",
"data": [
{
"id": 1,
"name": "Alice",
"email": "[email protected]"
},
{
"id": 2,
"name": "Bob",
"email": "[email protected]"
}
],
"pagination": {
"page": 1,
"limit": 10,
"totalItems": 2,
"totalPages": 1
}
}
Air sẽ tự động phát hiện thay đổi trong các file .go và restart server. Cấu hình trong .air.toml:
- Watched extensions:
.go,.tpl,.tmpl,.html - Excluded dirs:
tmp,vendor,testdata - Build delay: 1 giây
Tạo file trong middleware/:
package middleware
import "github.com/gin-gonic/gin"
func YourMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// Logic trước khi xử lý request
c.Next()
// Logic sau khi xử lý request
}
}
Đăng ký trong routes/routes.go:
r.Use(middleware.YourMiddleware())
Tạo file trong models/, ví dụ product.go:
package models
type Product struct {
ID uint `json:"id" gorm:"primaryKey"`
Name string `json:"name"`
Price float64 `json:"price"`
}
Thêm vào Auto Migration trong database/db.go:
DB.AutoMigrate(&models.User{}, &models.Product{})
- Thêm authentication (JWT)
- Thêm validation chi tiết hơn
- Thêm pagination cho GET endpoints
- Thêm unit tests
- Thêm Docker support
- Thêm logging vào file
- Thêm environment variables config
Contributions, issues và feature requests đều được chào đón!
This project is MIT licensed.
Your Name – GitHub
Happy Coding! 🚀