Skip to content
/ gin-boilerplate Public template
forked from liiijz/gin-boilerplate

⚡Fast-start scaffold for Gin Framework APIs. Includes MySQL, Redis-powered JWT auth, and a well-structured architecture to launch your Go projects quickly.

License

Notifications You must be signed in to change notification settings

yunyan/gin-boilerplate

 
 

Repository files navigation

Gin Boilerplate

English | 简体中文

A production-ready Go web application boilerplate built with Gin + GORM, featuring best practices and clean architecture.

✨ Features

  • 🚀 Complete Project Structure - Clean layered architecture (Controller, Service, Model, Router)
  • 🔐 JWT Authentication - Complete user authentication system
  • ⚙️ Multi-Environment Config - Support for development, production, and more (Viper-based)
  • 🗄️ Database ORM - GORM with auto-migration support
  • 🔒 Password Encryption - Bcrypt password hashing
  • 📝 Logging Middleware - Request logging
  • 🌐 CORS Support - Cross-Origin Resource Sharing middleware
  • 📦 Unified Response Format - Standardized API response structure
  • 🎨 Startup Banner - Spring Boot-style startup banner
  • 🧪 API Test Scripts - Multiple testing script options
  • 🧩 Plugin System - Modular plugin architecture for extensibility

📁 Project Structure

gin-boilerplate/
├── config/                 # Configuration files
│   ├── banner.txt         # Startup banner
│   ├── config.go          # Configuration loading logic
│   ├── default.yaml       # Default configuration
│   ├── development.yaml   # Development environment config
│   └── production.yaml    # Production environment config
├── controllers/           # Controller layer
│   ├── auth_controller.go # Authentication controller
│   └── user_controller.go # User controller
├── database/              # Database connection
│   └── database.go
├── middleware/            # Middlewares
│   ├── auth.go           # JWT authentication middleware
│   ├── cors.go           # CORS middleware
│   └── logger.go         # Logging middleware
├── models/                # Data models
│   ├── base.go           # Base model
│   └── user.go           # User model
├── plugins/               # Plugin system and implementations
│   ├── environment.go    # Plugin runtime environment
│   ├── plugin.go         # Plugin interface definition
│   ├── registry.go       # Plugin registry
│   └── guest/            # Guest plugin example
│       ├── controllers/
│       ├── models/
│       ├── services/
│       └── guest_plugin.go
├── router/                # Router layer
│   └── router.go
├── scripts/               # Scripts
│   ├── api-test.http     # HTTP test file
│   ├── api-test.sh       # Bash test script
│   └── init.sql          # Database initialization script
├── services/              # Business logic layer
│   ├── auth_service.go   # Authentication service
│   └── user_service.go   # User service
├── utils/                 # Utilities
│   ├── banner.go         # Banner utility
│   ├── jwt.go            # JWT utility
│   └── response.go       # Response utility
├── .gitignore
├── go.mod
├── main.go               # Application entry point
└── README.md

🚀 Quick Start

Option 1: Docker Deployment (Recommended)

Requirements

  • Docker
  • MySQL (external or separate container)

Steps

  1. Clone the project
git clone <repository-url>
cd gin-boilerplate
  1. Configure production settings

Edit config/production.yaml to match your database configuration:

database:
  host: "your-mysql-host"
  port: "3306"
  user: "your-db-user"
  password: "your-db-password"
  dbname: "gin_boilerplate_prod"
  1. Build Docker image
docker build -t gin-boilerplate:latest .
  1. Run container
docker run -d \
  --name gin-boilerplate \
  -p 8080:8080 \
  -v $(pwd)/config:/root/config \
  gin-boilerplate:latest
  1. Check logs
docker logs -f gin-boilerplate
  1. Stop container
docker stop gin-boilerplate
docker rm gin-boilerplate

The service runs on http://localhost:8080 by default.

Option 2: Local Development

Requirements

  • Go 1.19+
  • MySQL 5.7+

Steps

  1. Clone the Project
git clone <repository-url>
cd gin-boilerplate
  1. Install Dependencies
go mod tidy
  1. Database Setup

Initialize Database

mysql -u root -p < scripts/init.sql

Configure Database Connection

Edit config/development.yaml:

database:
  host: "localhost"
  port: "3306"
  user: "root"
  password: "your_password"
  dbname: "gin_boilerplate_dev"

jwt:
  secret: "your-secret-key"
  expire_time: 72
  1. Run the Application

Development Environment

go run main.go
# Or specify environment
go run main.go -e development

Production Environment

go run main.go -e production

The service runs on http://localhost:8080 by default.

🐳 Docker Deployment Details

Dockerfile Features

  • Multi-stage build: Minimizes final image size
  • Alpine-based: Lightweight and secure
  • Production optimized: CGO disabled for static binary

Using with Reverse Proxy

This application is designed to run behind a reverse proxy (Nginx, Traefik, etc.). The reverse proxy should handle:

  • SSL/TLS termination
  • Load balancing
  • Rate limiting
  • Static file serving (if needed)

Example Nginx configuration:

upstream gin_backend {
    server localhost:8080;
}

server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://gin_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Production Considerations

Before deploying to production:

  1. Change the JWT secret in config/production.yaml
  2. Configure external MySQL database
  3. Set up proper logging and monitoring
  4. Configure firewall rules
  5. Use reverse proxy for SSL/TLS
  6. Set up automated backups for database

📚 API Documentation

Authentication

User Registration

POST /api/v1/auth/register
Content-Type: application/json

{
  "username": "testuser",
  "email": "test@example.com",
  "password": "password123",
  "full_name": "Test User"
}

Response:

{
  "success": true,
  "code": 200,
  "message": "Success",
  "data": {
    "user": {
      "id": 1,
      "username": "testuser",
      "email": "test@example.com",
      "full_name": "Test User",
      "created_at": "2024-01-01T00:00:00Z"
    }
  }
}

User Login

POST /api/v1/auth/login
Content-Type: application/json

{
  "username": "testuser",
  "password": "password123"
}

Response:

{
  "success": true,
  "code": 200,
  "message": "Success",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": 1,
      "username": "testuser",
      "email": "test@example.com",
      "full_name": "Test User"
    }
  }
}

User Endpoints (Authentication Required)

All user-related endpoints require a token in the header:

Authorization: Bearer {your_token}

Get Current User Info

GET /api/v1/me
Authorization: Bearer {token}

Update Current User Info

PUT /api/v1/me
Authorization: Bearer {token}
Content-Type: application/json

{
  "full_name": "Updated Name",
  "email": "newemail@example.com"
}

Update Password

PUT /api/v1/me
Authorization: Bearer {token}
Content-Type: application/json

{
  "password": "newpassword123"
}

Health Check

GET /api/v1/health

Response:

{
  "status": "ok",
  "message": "Service is running"
}

🧪 API Testing

The project provides multiple API testing scripts:

1. HTTP File Testing (Recommended)

Use VS Code REST Client extension or IntelliJ IDEA HTTP Client:

# Open scripts/api-test.http file
# Click "Send Request" to execute tests

2. Bash Script Testing

For Linux/Mac users:

chmod +x scripts/api-test.sh
./scripts/api-test.sh

For Windows users (Git Bash):

bash scripts/api-test.sh

⚙️ Configuration

Configuration Hierarchy

  1. config/default.yaml - Base configuration (shared across all environments)
  2. config/{env}.yaml - Environment-specific configuration (overrides defaults)

Configuration Options

# Server configuration
server:
  port: "8080"              # Server port
  mode: "debug"             # Running mode: debug, release, test

# Database configuration
database:
  host: "localhost"         # Database host
  port: "3306"              # Database port
  user: "root"              # Database username
  password: ""              # Database password
  dbname: "gin_boilerplate" # Database name

# JWT configuration
jwt:
  secret: "your-secret-key" # JWT secret key (MUST change in production)
  expire_time: 24           # Token validity period (hours)

Custom Startup Banner

Edit the config/banner.txt file to customize your startup banner.

🔧 Development Guide

Adding New APIs

  1. Create Model (models/)
type Product struct {
    BaseModel
    Name  string `gorm:"not null" json:"name"`
    Price float64 `json:"price"`
}
  1. Create Service (services/)
type ProductService struct{}

func (s *ProductService) CreateProduct(product *models.Product) error {
    return database.GetDB().Create(product).Error
}
  1. Create Controller (controllers/)
type ProductController struct {
    productService *services.ProductService
}

func (c *ProductController) CreateProduct(ctx *gin.Context) {
    // Handle request
}
  1. Register Routes (router/router.go)
productController := controllers.NewProductController()
productRoutes := authenticated.Group("/products")
{
    productRoutes.POST("", productController.CreateProduct)
    productRoutes.GET("", productController.GetAllProducts)
}

Using Middleware

// Global middleware
r.Use(middleware.Logger())

// Route group middleware
authenticated := v1.Group("")
authenticated.Use(middleware.JWTAuth())

Database Migration

Add auto-migration for new models in main.go:

database.GetDB().AutoMigrate(
    &models.User{},
    &models.Product{}, // New model
)

🧩 Plugin System

The plugin system allows you to extend the application with modular features without modifying the core codebase.

Plugin Architecture

The plugin system provides:

  • Plugin Interface: Define plugin contract with Register() and RouterPath() methods
  • Plugin Registry: Auto-register plugins at startup using init() functions
  • Plugin Environment: Share dependencies (database, etc.) with plugins
  • Isolated Routes: Each plugin gets its own route group under /api/v1/plugin/{plugin-name}

Creating a Plugin

1. Create Plugin Structure

plugins/
└── myplugin/
    ├── controllers/
    │   └── myplugin_controller.go
    ├── models/
    │   └── myplugin_model.go
    ├── services/
    │   └── myplugin_service.go
    └── myplugin_plugin.go

2. Define Plugin Model (models/myplugin_model.go)

package models

import "gin-boilerplate/models"

type MyPluginData struct {
    models.BaseModel
    Name string `gorm:"not null" json:"name"`
}

3. Create Plugin Controller (controllers/myplugin_controller.go)

package controllers

import "github.com/gin-gonic/gin"

type MyPluginController struct{}

func NewMyPluginController() *MyPluginController {
    return &MyPluginController{}
}

func (c *MyPluginController) Hello(ctx *gin.Context) {
    ctx.JSON(200, gin.H{"message": "Hello from MyPlugin"})
}

4. Implement Plugin Interface (myplugin_plugin.go)

package myplugin

import (
    "gin-boilerplate/plugins"
    "gin-boilerplate/plugins/myplugin/controllers"
    "gin-boilerplate/plugins/myplugin/models"
    "github.com/gin-gonic/gin"
    "gorm.io/gorm"
)

// Auto-register plugin on import
func init() {
    plugins.Register("myplugin", NewMyPlugin)
}

type MyPlugin struct {
    db *gorm.DB
}

func NewMyPlugin(env *plugins.PluginEnvironment) plugins.Plugin {
    return &MyPlugin{db: env.DB}
}

func (p *MyPlugin) RouterPath() string {
    return "/myplugin"
}

func (p *MyPlugin) Register(group *gin.RouterGroup) error {
    // Auto-migrate plugin tables
    if err := p.db.AutoMigrate(&models.MyPluginData{}); err != nil {
        return err
    }

    // Register routes
    controller := controllers.NewMyPluginController()
    group.GET("/hello", controller.Hello)

    return nil
}

5. Import Plugin in main.go

import (
    _ "gin-boilerplate/plugins/myplugin" // Auto-register plugin
)

Plugin Routes

All plugins are automatically mounted under /api/v1/plugin/:

  • Guest plugin: http://localhost:8080/api/v1/plugin/guest/*
  • Your plugin: http://localhost:8080/api/v1/plugin/myplugin/*

Example: Guest Plugin

The project includes a guest plugin example at plugins/guest/ that demonstrates:

  • Plugin registration and initialization
  • Route setup under /api/v1/plugin/guest
  • Database model auto-migration
  • Controller implementation

Test the Guest Plugin:

curl -X POST http://localhost:8080/api/v1/plugin/guest/login

Plugin Best Practices

  1. Self-contained: Keep plugin code isolated in its own directory
  2. Database migrations: Use AutoMigrate() in plugin's Register() method
  3. Naming convention: Use lowercase for plugin names and route paths
  4. Error handling: Return errors from Register() for proper initialization
  5. Dependencies: Access shared resources through PluginEnvironment

🛡️ Security Recommendations

  1. Change JWT Secret: Use a strong secret key in production
  2. HTTPS: Use HTTPS in production environments
  3. Database Password: Don't commit production config files to Git
  4. Input Validation: Use Gin's binding for user input validation
  5. Rate Limiting: Add API rate limiting middleware as needed

📦 Dependencies

  • Gin - Web framework
  • GORM - ORM library
  • Viper - Configuration management
  • JWT - JWT authentication
  • bcrypt - Password encryption

📝 TODO

  • Add unit tests
  • Add API documentation (Swagger)
  • Add Docker support
  • Add rate limiting middleware
  • Add cache support (Redis)
  • Add file logging

📄 License

MIT License

🤝 Contributing

Issues and Pull Requests are welcome!


Happy Coding! 🎉

About

⚡Fast-start scaffold for Gin Framework APIs. Includes MySQL, Redis-powered JWT auth, and a well-structured architecture to launch your Go projects quickly.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 90.7%
  • Shell 7.7%
  • Dockerfile 1.6%