A production-ready RESTful blog API example built with Go and Gin framework, demonstrating real-world patterns and best practices.
Project Overview
This project is a comprehensive blog backend API system that provides complete article and tag management functionalities, along with features like JWT authentication, image upload, QR code generation, and Excel import/export.
Tech Stack
| Category | Technology |
|---|---|
| Language | Go |
| Web Framework | Gin |
| ORM | GORM |
| Database | MySQL |
| Cache | Redis (via Redigo) |
| Authentication | JWT (jwt-go) |
| Configuration | go-ini |
| API Documentation | Swagger |
| Excel Processing | excelize, xlsx |
| Image Processing | freetype, barcode |
| Validation | beego/validation |
Project Structure
go-gin-example/
├── conf/ # Configuration files
│ └── app.ini # Application configuration
├── docs/ # Documentation
│ ├── sql/ # Database scripts
│ │ └── blog.sql # Database schema
│ └── swagger/ # Swagger documentation
├── middleware/ # Middleware
│ └── jwt/ # JWT authentication middleware
│ └── jwt.go
├── models/ # Data models (ORM)
│ ├── article.go # Article model
│ ├── auth.go # Auth model
│ ├── models.go # Database initialization
│ └── tag.go # Tag model
├── pkg/ # Shared packages
│ ├── app/ # Application utilities
│ │ ├── form.go # Form binding
│ │ ├── request.go # Request handling
│ │ └── response.go # Response formatting
│ ├── e/ # Error codes
│ │ ├── cache.go # Cache key constants
│ │ ├── code.go # Error code definitions
│ │ └── msg.go # Error messages
│ ├── export/ # Excel export utilities
│ │ └── excel.go
│ ├── file/ # File utilities
│ │ └── file.go
│ ├── gredis/ # Redis client
│ │ └── redis.go
│ ├── logging/ # Logging utilities
│ │ ├── file.go
│ │ └── log.go
│ ├── qrcode/ # QR code generation
│ │ └── qrcode.go
│ ├── setting/ # Configuration management
│ │ └── setting.go
│ ├── upload/ # Image upload utilities
│ │ └── image.go
│ └── util/ # Common utilities
│ ├── jwt.go # JWT utilities
│ ├── md5.go # MD5 hashing
│ ├── pagination.go # Pagination helper
│ └── util.go
├── routers/ # Route definitions
│ ├── api/ # API handlers
│ │ ├── v1/ # API v1 handlers
│ │ │ ├── article.go # Article endpoints
│ │ │ └── tag.go # Tag endpoints
│ │ ├── auth.go # Authentication endpoint
│ │ └── upload.go # Image upload endpoint
│ └── router.go # Route initialization
├── runtime/ # Runtime resources
│ ├── fonts/ # Font files
│ └── qrcode/ # QR code resources
├── service/ # Business logic layer
│ ├── article_service/ # Article services
│ │ ├── article.go # Article CRUD operations
│ │ └── article_poster.go # Poster generation
│ ├── auth_service/ # Auth services
│ │ └── auth.go
│ ├── cache_service/ # Cache key generation
│ │ ├── article.go
│ │ └── tag.go
│ └── tag_service/ # Tag services
│ └── tag.go
├── Dockerfile # Docker build file
├── Makefile # Build automation
├── go.mod # Go module definition
├── go.sum # Dependency checksums
└── main.go # Application entry point
Architecture
The project follows a layered architecture pattern:
┌─────────────────────────────────────────────────────────────┐
│ HTTP Requests │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Middleware Layer │
│ (JWT Authentication) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Router Layer │
│ (routers/api/v1/*.go) │
│ - Request validation │
│ - Parameter binding │
│ - Response formatting │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Service Layer │
│ (service/*/*.go) │
│ - Business logic │
│ - Cache management │
│ - Cross-model operations │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Model Layer │
│ (models/*.go) │
│ - Database operations │
│ - CRUD methods │
│ - Data structures │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Storage Layer │
│ MySQL (Primary) + Redis (Cache) │
└─────────────────────────────────────────────────────────────┘
Feature Tree
Go Gin Blog API
├── Authentication
│ └── JWT Login Validation
│ ├── Token Generation (3-hour expiry)
│ ├── Token Validation
│ └── Token Refresh
├── Article Management
│ ├── Create Article
│ ├── Read Article (with Redis caching)
│ ├── Update Article
│ ├── Delete Article (soft delete)
│ ├── List Articles (paginated)
│ ├── Count Articles
│ └── Generate Article Poster
│ ├── Embed QR Code
│ ├── Apply Background Image
│ ├── Render Text Overlay
│ └── Save Merged Image
├── Tag Management
│ ├── CRUD Operations
│ │ ├── Create Tag
│ │ ├── Read Tags (paginated, cached)
│ │ ├── Update Tag
│ │ └── Delete Tag (soft delete)
│ ├── Export Tags to Excel
│ └── Import Tags from Excel
├── File Upload
│ └── Image Upload
│ ├── Format validation (.jpg, .jpeg, .png)
│ ├── Size validation (max 5MB)
│ └── MD5-based naming
├── API Documentation
│ └── Swagger UI (/swagger/*any)
└── Static File Serving
├── Exported Excel files (/export)
├── Uploaded images (/upload/images)
└── Generated QR codes (/qrcode)
API Endpoints
Public Endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /auth |
User authentication, returns JWT token |
| GET | /swagger/*any |
Swagger API documentation |
| POST | /upload |
Image upload |
| POST | /tags/export |
Export tags to Excel |
| POST | /tags/import |
Import tags from Excel |
Protected Endpoints (Require JWT Token)
Tags
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/tags |
Get tag list (paginated) |
| POST | /api/v1/tags |
Create new tag |
| PUT | /api/v1/tags/:id |
Update tag by ID |
| DELETE | /api/v1/tags/:id |
Delete tag by ID |
Articles
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/articles |
Get article list (paginated) |
| GET | /api/v1/articles/:id |
Get article by ID |
| POST | /api/v1/articles |
Create new article |
| PUT | /api/v1/articles/:id |
Update article by ID |
| DELETE | /api/v1/articles/:id |
Delete article by ID |
| POST | /api/v1/articles/poster/generate |
Generate article poster with QR code |
Database Schema
Tables
blog_auth - User authentication
- id: INT (PK, AUTO_INCREMENT) - username: VARCHAR(50) - password: VARCHAR(50)
blog_tag - Article tags
- id: INT (PK, AUTO_INCREMENT) - name: VARCHAR(100) - Tag name - created_on: INT - Creation timestamp - created_by: VARCHAR(100) - Creator - modified_on: INT - Modification timestamp - modified_by: VARCHAR(100) - Modifier - deleted_on: INT - Deletion timestamp (soft delete) - state: TINYINT - Status (0: disabled, 1: enabled)
blog_article - Articles
- id: INT (PK, AUTO_INCREMENT) - tag_id: INT (FK) - Associated tag ID - title: VARCHAR(100) - Article title - desc: VARCHAR(255) - Description - content: TEXT - Article content - cover_image_url: VARCHAR(255) - Cover image URL - created_on: INT - Creation timestamp - created_by: VARCHAR(100) - Creator - modified_on: INT - Modification timestamp - modified_by: VARCHAR(255) - Modifier - deleted_on: INT - Deletion timestamp (soft delete) - state: TINYINT - Status
Configuration
Configuration is managed through conf/app.ini:
[app] PageSize = 10 # Pagination page size JwtSecret = 233 # JWT signing secret PrefixUrl = http://127.0.0.1:8000 RuntimeRootPath = runtime/ ImageSavePath = upload/images/ ImageMaxSize = 5 # Max image size in MB ImageAllowExts = .jpg,.jpeg,.png ExportSavePath = export/ QrCodeSavePath = qrcode/ FontSavePath = fonts/ LogSavePath = logs/ [server] RunMode = debug # debug or release HttpPort = 8000 ReadTimeout = 60 # seconds WriteTimeout = 60 # seconds [database] Type = mysql User = root Password = rootroot Host = 127.0.0.1:3306 Name = blog TablePrefix = blog_ [redis] Host = 127.0.0.1:6379 Password = MaxIdle = 30 MaxActive = 30 IdleTimeout = 200
Getting Started
Prerequisites
- Go 1.13+
- MySQL 5.6+
- Redis
Database Setup
- Create a MySQL database named
blog - Execute the SQL script:
mysql -u root -p blog < docs/sql/blog.sqlConfiguration
- Edit
conf/app.inito match your environment - Update database credentials
- Update Redis connection settings
Running the Application
# Build make build # Run ./go-gin-example # Or run directly go run main.go
The server will start at http://localhost:8000
Using Docker
# Build image docker build -t go-gin-example . # Run container docker run -p 8000:8000 go-gin-example
API Usage Examples
1. Get Authentication Token
curl -X POST http://localhost:8000/auth \
-d "username=test&password=test123"Response:
{
"code": 200,
"msg": "ok",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}2. Create a Tag
curl -X POST "http://localhost:8000/api/v1/tags?token=YOUR_TOKEN" \ -d "name=Go&created_by=admin&state=1"
3. Get Tags List
curl "http://localhost:8000/api/v1/tags?token=YOUR_TOKEN"4. Create an Article
curl -X POST "http://localhost:8000/api/v1/articles?token=YOUR_TOKEN" \ -d "tag_id=1&title=Hello Gin&desc=Introduction to Gin&content=Article content...&created_by=admin&cover_image_url=http://example.com/image.jpg&state=1"
5. Upload an Image
curl -X POST http://localhost:8000/upload \
-F "image=@/path/to/image.jpg"6. Export Tags to Excel
curl -X POST http://localhost:8000/tags/export
Key Design Patterns
1. Soft Delete
All models use soft delete by setting deleted_on timestamp instead of actual deletion.
2. Redis Caching
Articles and tags are cached in Redis with 1-hour TTL to reduce database load.
3. Service Layer Pattern
Business logic is separated into service layer, keeping handlers thin and focused on request/response handling.
4. Unified Response Format
All API responses follow consistent format:
{
"code": 200,
"msg": "ok",
"data": {}
}5. Custom GORM Callbacks
Custom callbacks for automatic timestamp management:
CreatedOnset on createModifiedOnupdated on modificationsDeletedOnset on soft delete
Error Codes
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Invalid parameters |
| 500 | Internal server error |
| 10001 | Tag already exists |
| 10003 | Tag not found |
| 10011 | Article not found |
| 20001 | Token validation failed |
| 20002 | Token expired |
| 20003 | Token generation error |
| 20004 | Authentication failed |
| 30001 | Image save failed |
| 30002 | Image check failed |
| 30003 | Invalid image format |
Development Commands
# Build make build # Run code analysis make tool # Run linter make lint # Clean build artifacts make clean
License
MIT License - See LICENSE for details.
Credits
Project by EDDYCJY