ThinkGin 3.14.1 文档
一站式 Go Web 框架参考手册。按"入门 → 核心 → 开发与部署"的顺序,讲清楚如何把 ThinkGin 装起来,又如何把它稳定交付到生产环境。
快速开始
三行命令把 ThinkGin 跑起来,5 分钟完成第一个接口。
架构设计
MVC 分层、请求生命周期、组件边界与扩展点。
Session & JWT
内置会话管理与 HS256 鉴权中间件,生产可用。
监控与探针
Prometheus 指标、OpenTelemetry 链路、K8s 探针一体化。
配置管理
13 个模块化 YAML,THINKGIN_* 环境变量覆盖。
部署指南
Docker、Kubernetes、systemd 与交叉编译实战。
项目介绍
ThinkGin 3.14.1 是一个基于 Gin 1.12 构建的生产级 Go Web 框架,定位为单体业务后台脚手架,强调工程纪律 · 配置秩序 · 开箱即交付。近期版本完成 P0 安全加固(JWT 密钥外置 / CORS 安全默认 / Session 强制 HttpOnly / Redis Flush 限定前缀 / metrics 鉴权姿态)、P1 正确性修复(熔断器并发与低流量、缓存击穿 singleflight、内存缓存 goroutine 泄漏)、P2 工程质量打磨(CLI 测试补齐、迁移文档统一、loader 去重)、P3 交付能力(完整业务模块范例 article、生产级 Dockerfile)与长连接健壮性增强(WebSocket 心跳保活、config 命令脱敏、心跳停止并发修复),
自定义中间件注册表(route.RegisterMiddleware),业务可无需 fork 即可按名注入或覆盖任何内置中间件;
同时保留安全加固(CSRF/JWT/CORS)、并发安全(atomic.Pointer 配置热更新)、路由级熔断器、lumberjack 日志轮转等能力。
⚙️ 工程纪律
三平台 CI + -race 强制门禁,lint + 70%+ 测试覆盖,面向生产的工程品质。
🔧 模块化
完全模块化的 YAML 配置管理。
📊 可观测
日志、监控、链路追踪能力分层落地。
🛡️ 企业级
生产就绪的安全性与稳定性设计。
🎨 易用性
简洁的 API 表达与清晰的文档组织。
🌐 多场景
支持 Web、API、微服务等多种形态。
核心特性
| 特性 | 描述 |
|---|---|
| MVC 架构 | 标准的 Model-View-Controller 分层,配合 cmd/scaffold 一键生成模块骨架 |
| 模块化配置 | 13 个独立 YAML,THINKGIN_* 前缀环境变量覆盖,默认不预置任何真实依赖 |
| GORM 多数据源 | MySQL / PostgreSQL / SQLite,GORM OTel 插件把 SQL 纳入同一条 HTTP trace |
| Redis 多实例 | redis/go-redis v9,启动期 Ping 探活;可复用为 Session 后端 |
| Session 运行时 | memory / redis 双 driver,Cookie 安全标志自动透传 |
| JWT 鉴权 | HS256 签发与校验,严格拒绝 alg=none 伪造 |
| Prometheus | HTTP 四维 + 运行时 + 业务指标,分模块启停 |
| 链路追踪 | OpenTelemetry TracerProvider;可通过 OTLP 上报 Jaeger / Tempo / Zipkin |
| K8s 探针 | /livez 仅验证进程存活;/readyz 并发 Ping DB / Redis,降级返 503 |
| 优雅停机 | 信号监听 + 超时 + DB / Cache / Tracer 依序释放 |
| Logger 接口 | 抽象 Logger 接口,内置 logrus + slog 双适配器,WithFields 线程安全 |
| HTTPS 双监听 | 配置 server.https.enabled=true 后 HTTP/HTTPS 并发启动,TLS 1.2+ |
| ServiceContext | 聚合 Config/Logger/DB/Cache,通过 SvcFromGin(c) 请求链路获取,替代全局单例 |
| 安全中间件 | CSRF 双重提交 Cookie + Gzip 压缩 + 安全响应头(X-Frame-Options 等),middleware.global
按名启用 |
| Swagger / OpenAPI | 零 Go 依赖 Swagger UI,维护 docs/openapi.yaml 即可在 /swagger/ 预览
|
| 数据库迁移 | GORM Migrator:Register → Migrate → Rollback → Status,Go 函数注册,类型安全 |
| 配置热更新 | fsnotify 监听 YAML 变更,去抖 500ms,回调通知业务层刷新运行时状态 |
| Redis 分布式限流 | Lua 脚本原子令牌桶,Redis 故障自动降级为 no-op |
| i18n 运行时 | YAML 翻译文件 + Accept-Language / ?lang= 检测 +
T(c, key)
|
快速开始
用几条命令把服务跑起来,是评估一个框架最直接的方式。
环境要求
- Go 版本:1.25 或更高。Gin 1.12 通过 quic-go 间接要求 Go 1.25+
- 操作系统:Windows 10+ / macOS 10.14+ / Linux(Ubuntu 20.04+, CentOS 7+)
- 内存:最低 512MB,推荐 1GB+
- 磁盘空间:最低 100MB
从源码运行
# 源码仓库:Gitee (国内) 或 GitHub (国外)
git clone https://gitee.com/libaicode/thinkgin.git
# git clone https://github.com/thinkgin/thinkgin.git
cd thinkgin
go mod tidy
go run main.go
# 验证运行
curl http://localhost:8000/
编译后运行
# 编译项目
go build -o thinkgin main.go
# Linux / macOS
./thinkgin
# Windows
thinkgin.exe
Docker 运行
docker build -t thinkgin:latest .
docker run -p 8000:8000 thinkgin:latest
http://localhost:8000/,或调用接口
http://localhost:8000/index/hello;若启用了 Prometheus,则 /metrics 可直接查看指标。
环境配置
推荐:Go 1.25+ 现代化配置
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOSUMDB=sum.golang.google.cn
# 验证配置
go env | grep -E "(GO111MODULE|GOPROXY|GOSUMDB)"
macOS / Linux (Bash/Zsh)
export GO111MODULE=on
export GOPROXY=https://goproxy.cn,direct
export GOSUMDB=sum.golang.google.cn
echo 'export GO111MODULE=on' >> ~/.bashrc
echo 'export GOPROXY=https://goproxy.cn,direct' >> ~/.bashrc
echo 'export GOSUMDB=sum.golang.google.cn' >> ~/.bashrc
source ~/.bashrc
Windows (PowerShell)
$env:GO111MODULE="on"
$env:GOPROXY="https://goproxy.cn,direct"
$env:GOSUMDB="sum.golang.google.cn"
[Environment]::SetEnvironmentVariable("GO111MODULE", "on", "User")
[Environment]::SetEnvironmentVariable("GOPROXY", "https://goproxy.cn,direct", "User")
[Environment]::SetEnvironmentVariable("GOSUMDB", "sum.golang.google.cn", "User")
架构设计
项目结构
thinkgin/ # 项目根目录
├── app/ # 应用层
│ ├── index/ # 模块示例
│ │ ├── controller/ # 控制器层
│ │ ├── model/ # 数据模型层
│ │ └── view/ # 视图层
│ └── config.go # 配置管理入口
├── config/ # 配置文件目录
│ ├── app.yaml # 应用主配置
│ ├── server.yaml # 服务器配置
│ ├── database.yaml # 数据库配置
│ ├── log.yaml # 日志配置
│ └── prometheus.yaml # 监控配置
├── extend/ # 扩展组件
│ └── middleware/ # 中间件
├── route/ # 路由定义
├── public/ # 静态资源
├── runtime/ # 运行时文件
└── main.go # 程序入口
请求流程
HTTP Request → Router → Middleware → Controller
↓
Model ↔ Database
↓
View / JSON → HTTP Response
服务启动示例
config := app.GetConfig()
logger := app.GetLogger()
appInstance, err := framework.New(
framework.WithConfig(config),
framework.WithLogger(logger),
framework.WithShutdownTimeout(10*time.Second),
)
if err != nil {
logger.Fatalf("应用初始化失败: %v", err)
}
if err := appInstance.Run(ctx); err != nil {
logger.Fatalf("服务器运行失败: %v", err)
}
配置管理
ThinkGin 采用模块化配置架构,把不同功能的配置拆分到独立的 YAML 文件中。
配置文件矩阵
| 配置文件 | 功能 | 重要性 |
|---|---|---|
| app.yaml | 应用元信息 + JWT 密钥 | ⭐⭐⭐ |
| server.yaml | 监听地址 / 端口 / 超时 / 运行模式 | ⭐⭐⭐ |
| database.yaml | MySQL / PostgreSQL / SQLite 连接 | ⭐⭐⭐ |
| cache.yaml | Redis 多实例 | ⭐⭐ |
| session.yaml | Session driver / Cookie 安全标志 | ⭐⭐ |
| middleware.yaml | 全局中间件列表(session / jwt / cors / rate_limit…) | ⭐⭐ |
| log.yaml | 日志级别 / 格式 / 轮转策略 | ⭐⭐ |
| prometheus.yaml | 指标路径 + 分模块启停 | ⭐⭐ |
| trace.yaml | OpenTelemetry 采样率 / 导出方式 | ⭐ |
使用示例
// 获取配置实例
config := app.GetConfig()
// 访问不同模块配置
appName := config.App.Name
serverPort := config.Server.HTTP.Port
dbConfig := config.Database.Default
app.yaml
app:
name: "ThinkGin"
version: "3.14.1"
debug: true
timezone: "Asia/Shanghai"
swagger_enabled: true # 启用 /swagger/ 端点
jwt:
secret: "" # 留空,改用环境变量 THINKGIN_APP_JWT_SECRET 注入(v3.11.1+)
expire: 7200 # 秒
server.yaml
server:
http:
host: "0.0.0.0"
port: 8000
read_timeout: 60
write_timeout: 60
mode: "debug"
其他配置模块
database.yaml
支持 MySQL / PostgreSQL / SQLite / Redis。
cache.yaml
支持 Redis、内存、文件缓存。
session.yaml
memory / redis 双 driver,含 Cookie 安全标志。
middleware.yaml
global 列表按名注册:session / jwt / cors / rate_limit…
trace.yaml
OpenTelemetry 采样率 / 导出方式 / tags。
lang (i18n)
YAML 翻译文件 + Accept-Language 检测 + T(c, key) 便捷函数。
Session
内置 memory / redis 两种 Store,Cookie 自动携带 HttpOnly /
Secure / SameSite 安全标志。Session ID 采用 256-bit crypto/rand +
base64url 编码。
启用
# config/middleware.yaml
middleware:
global:
- recovery
- request_id
- session # 追加这一行即可
业务代码
import "thinkgin/app/session"
func Profile(c *gin.Context) {
s := session.From(c)
s.Set("user_id", 42)
if err := s.Save(c.Request.Context()); err != nil {
c.AbortWithError(500, err)
return
}
c.JSON(200, gin.H{"ok": true})
}
func Logout(c *gin.Context) {
_ = session.From(c).Destroy(c.Request.Context())
session.ClearCookie(c)
}
driver 切换
| driver | 适用场景 |
|---|---|
memory |
单实例 / 开发调试;默认值 |
redis |
多副本部署;引用 database.yaml 中的 redis 连接 |
file / database |
未实现 |
JWT 鉴权
HS256 签发与校验,严格拒绝 alg=none、非 HMAC 算法;密钥缺失时拒绝签发,避免"空密钥 token"。
配置
# config/app.yaml
app:
jwt:
secret: "your-secret-key"
expire: 7200 # 秒
签发与校验
import "thinkgin/extend/middleware"
// 签发(ttl=0 使用 app.jwt.expire,仍为 0 兜底 2 小时)
token, err := middleware.JWTIssue(
"42",
map[string]any{"role": "admin"},
0,
)
// 保护路由:middleware.yaml 加 "jwt",或在分组上 Use
api := r.Group("/api/v1", middleware.JWTAuth())
api.GET("/me", func(c *gin.Context) {
claims := middleware.JWTFromContext(c)
c.JSON(200, gin.H{
"uid": claims.Subject,
"role": claims.Extra["role"],
})
})
过期、签名非法、格式错误都统一走 APIError(401),响应体对外隐藏内部实现细节。
健康探针
两个探针的语义严格遵守 K8s 约定。
| 端点 | 语义 | 用途 |
|---|---|---|
GET /livez |
仅验证 HTTP 处理管道存活 | livenessProbe;失败即重启 Pod |
GET /readyz |
并发 Ping 所有已注册的 DB / Redis | readinessProbe;失败时 k8s 摘掉 Pod 流量 |
/readyz 用 2s 硬超时,任一依赖不可达就返回 503 + 详细组件状态;没配置任何依赖时仍返回 200,兼容"纯 HTTP 应用"场景。
curl -i http://localhost:8000/readyz
# HTTP/1.1 200 OK
# {"status":"ok","components":{"database":{"ok":true,"elapsed":"2ms"}}}
日志系统
基于 slog(Go 1.21+ 标准库)的结构化日志系统,支持 JSON / Text 双格式,按时间或大小自动切割;v3.10 起默认 driver 已从 logrus 切换为 slog。
日志级别
| 级别 | 使用场景 | 示例 |
|---|---|---|
| trace | 详细跟踪 | 函数进入 / 退出 |
| debug | 调试信息 | 变量值、流程状态 |
| info | 一般信息 | 业务流程记录 |
| warn | 警告信息 | 潜在问题提醒 |
| error | 错误信息 | 异常处理 |
| fatal | 致命错误 | 程序无法继续 |
| panic | 恐慌级别 | 触发 panic |
使用方法
import "thinkgin/extend/middleware"
// 记录信息日志
middleware.BusinessLogger("info", "用户登录成功", map[string]interface{}{
"user_id": 123,
"username": "john",
"ip": "192.168.1.1",
})
// 记录错误日志
middleware.BusinessLogger("error", "数据库连接失败", map[string]interface{}{
"error": err.Error(),
"database": "mysql",
})
直接使用 logrus 实例
import "thinkgin/app"
logger := app.GetLogger()
logger.WithFields(logrus.Fields{
"user_id": 123,
"action": "update_profile",
}).Info("用户更新资料")
日志文件
- 位置:
runtime/log/ - 命名:
system.YYYYMMDD.log - 软链:
system.log - 自动清理:超过设定天数的旧日志会被删除
开发环境配置
log:
default:
level: "debug"
format: "text"
file:
max_age: 3
rotation_time: 6
生产环境配置
log:
default:
level: "info"
format: "json"
file:
max_age: 30
rotation_time: 24
监控体系
ThinkGin 3.14.1 集成 Prometheus 监控服务,提供完整的应用性能监控和业务指标采集能力。
监控特性
- HTTP 请求监控:自动记录请求数量、响应时间、请求体大小、响应体大小
- 系统资源监控:CPU 使用率、内存使用量、进程信息
- 业务指标:Counter / Histogram / Gauge 三种类型
- 配置化:所有监控参数均可配置调整
- 安全认证:支持基础认证保护监控端点
- 自定义标签:支持自定义标签与命名空间
快速启用
# config/app.yaml
app:
monitoring:
prometheus_enabled: true # 总开关
go run main.go
curl http://localhost:8000/metrics
k8s 探针
GET /livezGET /readyz
prometheus.yaml 核心配置
prometheus:
enabled: true # 总开关;false 时不注册 /metrics
path: "/metrics"
service_name: "thinkgin"
namespace: "app"
metrics:
http:
enabled: true
include_path: false # 动态路径建议 false,避免 label 爆炸
system:
enabled: true
business:
enabled: true
业务埋点示例
import (
"time"
"thinkgin/extend/middleware"
"github.com/gin-gonic/gin"
)
func YourHandler(c *gin.Context) {
start := time.Now()
if counter := middleware.BusinessCounter("api_calls", []string{"endpoint", "status"}); counter != nil {
counter.WithLabelValues("/api/users", "success").Inc()
}
if histogram := middleware.BusinessHistogram("api_duration", []string{"endpoint"}, nil); histogram != nil {
histogram.WithLabelValues("/api/users").Observe(time.Since(start).Seconds())
}
if gauge := middleware.BusinessGauge("online_users", []string{"type"}); gauge != nil {
gauge.WithLabelValues("active").Set(123)
}
}
常用 PromQL
# HTTP 请求总数
app_http_requests_total
# 平均响应时间
rate(app_http_request_duration_seconds_sum[5m]) / rate(app_http_request_duration_seconds_count[5m])
# 错误率(5xx)
rate(app_http_requests_total{status=~"5.."}[5m]) / rate(app_http_requests_total[5m])
# 内存使用量
app_system_memory_usage_bytes
自定义中间件注册表 v3.11.0 NEW
v3.10.x 之前,route.resolveMiddleware 是一个 18 分支的 hardcoded switch,业务想注入自定义中间件
唯一的方式是 fork 框架——这违反了开闭原则。v3.11.0 通过 route.RegisterMiddleware
让你在 main 早期注册任意命名工厂,之后即可在 config/middleware.yaml 的
global / groups 列表里按名启用。
基本用法
package main
import (
"github.com/gin-gonic/gin"
"thinkgin/app"
"thinkgin/framework"
"thinkgin/route"
)
func main() {
// 1. 在 framework.New 之前注册自定义中间件
route.RegisterMiddleware("audit", func() gin.HandlerFunc {
return func(c *gin.Context) {
app.GetLogger().Infof("audit: %s %s", c.Request.Method, c.Request.URL.Path)
c.Next()
}
})
// 2. 也可以覆盖内置中间件(例如替换默认 access_log)
route.RegisterMiddleware("access_log", func() gin.HandlerFunc {
return myaccesslog.New()
})
a, _ := framework.New()
_ = a.Run(nil)
}
然后在 config/middleware.yaml 的全局列表里按名启用:
middleware:
global:
- recovery
- audit # ← 自定义中间件
- access_log # ← 此处会用到上面注册的覆盖版本
API 参考
| 函数 | 说明 |
|---|---|
RegisterMiddleware(name, factory) |
注册中间件工厂,重复注册同名将覆盖;空名或 nil 工厂被静默忽略 |
UnregisterMiddleware(name) |
移除已注册项;主要用于测试隔离 |
LookupMiddleware(name) |
查询并构造一个 gin.HandlerFunc 实例;未注册返回 nil |
HasMiddleware(name) |
仅做存在性判断,零分配,不构造 handler |
设计要点
- 工厂语义:注册的是
func() gin.HandlerFunc,每次Use时调用工厂得到独立实例,避免共享状态污染(例如令牌桶/熔断器内部计数器)。 - 解析顺序:自定义注册表优先 → 未命中回落到内置
switch→ 仍未命中静默忽略,100% 向后兼容 v3.10.x 配置。 - 覆盖语义:注册同名中间件可覆盖内置实现(如自定义 logger 替代
access_log)。 - 线程安全:基于
sync.Map,运行期读零开销;典型场景是main启动期一次性注册。
route.InitRouter()(即 framework.New)之前完成,否则
YAML 配置解析时找不到自定义名称会被静默跳过。
ServiceContext 依赖注入
v3.3.0 引入 ServiceContext 替代全局单例,将 Config / Logger / DB / Cache 聚合到一个显式结构体中。
工作原理
// 在 Handler 中获取 ServiceContext
svc := app.SvcFromGin(c)
svc.Log.Infof("当前应用: %s", svc.Config.App.Name)
// ServiceContext 通过 SvcMiddleware 自动注入到 gin.Context
// 未注入时会从全局变量兜底,保持向后兼容
结构定义
type ServiceContext struct {
Config *GlobalConfig
Log Logger
DB *gorm.DB // 默认数据库连接
Cache *redis.Client // 默认 Redis 连接
}
app.GetConfig() / app.GetLogger()
全局函数,业务可逐步迁移,不会 break 现有代码。
安全中间件
v3.3.0 新增三大安全中间件,v3.6.1 进一步修复 CSRF 时序攻击,通过 middleware.global 列表按名启用。
CSRF 防护
# config/middleware.yaml
middleware:
global:
- recovery
- csrf # 双重提交 Cookie 方案
// 前端通过 Header 或表单字段提交 token
// Header: X-CSRF-Token: <token>
// 表单: _csrf_token=<token>
// 模板中使用:{{ .csrf_token }}
Gzip 压缩
middleware:
global:
- gzip # 自动压缩响应
仅当客户端 Accept-Encoding 包含 gzip 时压缩,sync.Pool 复用 Writer,减少内存分配。
安全响应头
middleware:
global:
- secure_headers # 默认启用 X-Content-Type-Options/X-Frame-Options 等
config:
secure_headers:
X-Frame-Options: "SAMEORIGIN" # 覆盖默认值
Content-Security-Policy: "default-src 'self'" # 新增头
X-Content-Type-Options: "" # 空值 = 禁用
Swagger / OpenAPI
零 Go 依赖的 Swagger UI 端点,通过 CDN 加载 swagger-ui。
启用
# config/app.yaml
app:
debug: true # debug 模式自动启用
# 或显式开启:
swagger_enabled: true
端点
GET /swagger/— Swagger UI 界面GET /swagger/doc.yaml— OpenAPI YAML 规范GET /swagger/doc.json— OpenAPI JSON 规范
规范文件
维护 docs/openapi.yaml 即可,修改后刷新 Swagger UI 即时生效。
数据库迁移
基于 GORM 的迁移管理器,迁移以 Go 函数形式注册,保持类型安全。
使用示例
import "thinkgin/app/database"
m := database.NewMigrator(db)
m.Register(
database.Migration{
Version: "001_create_users",
Up: func(db *gorm.DB) error {
return db.Exec("CREATE TABLE users (id INT PRIMARY KEY, name TEXT)").Error
},
Down: func(db *gorm.DB) error {
return db.Exec("DROP TABLE IF EXISTS users").Error
},
},
)
// 执行迁移(幂等)
m.Migrate()
// 回退最后 1 个
m.Rollback(1)
// 查看状态
status, _ := m.Status()
配置热更新
使用 fsnotify 监听配置目录 YAML 文件变更,去抖 500ms 后自动重新加载。
使用方式
watcher, err := app.WatchConfig("config", func(cfg *app.GlobalConfig) {
log.Infof("配置已重载: app.name=%s", cfg.App.Name)
// 在此刷新运行时状态,如限流阈值、日志级别等
})
defer watcher.Close()
main.go 中显式调用 WatchConfig。Logger
等有状态组件建议不热换。
Redis 分布式限流
基于 Redis Lua 脚本的原子性令牌桶算法,适用于多实例部署统一限流。
配置
# config/middleware.yaml
middleware:
global:
- redis_rate_limit
config:
redis_rate_limit:
requests_per_minute: 120
redis_store: "default" # 对应 cache.yaml 中的 store 名称
国际化 i18n
YAML 翻译文件 + 自动语言检测 + 模板变量替换。
翻译文件
# lang/zh-CN.yaml
welcome: "欢迎, {{.Name}}!"
hello: "你好"
# lang/en.yaml
welcome: "Welcome, {{.Name}}!"
hello: "Hello"
使用方式
import "thinkgin/extend/i18n"
// 初始化
bundle := i18n.NewBundle("lang", "zh-CN")
bundle.LoadAll()
// 注册中间件
r.Use(i18n.Middleware(bundle))
// Handler 中翻译
func Hello(c *gin.Context) {
msg := i18n.T(c, "welcome", map[string]string{"Name": "张三"})
c.String(200, msg)
// 输出:欢迎, 张三!(中文)或 Welcome, 张三!(英文)
}
语言检测优先级
?lang=en查询参数(最高优先级)Accept-Language请求头- fallback 默认语言
WebSocket
基于 gorilla/websocket 封装,一行代码将 HTTP 请求升级为 WebSocket 连接。
Echo 示例
import "thinkgin/extend/websocket"
r.GET("/ws", websocket.Handler(func(conn *websocket.Conn) {
defer conn.Close()
for {
mt, msg, err := conn.Conn.ReadMessage()
if err != nil { break }
conn.WriteSafeMessage(mt, msg) // echo back
}
}))
Hub 广播模型
适用于聊天室、实时通知等场景,自动管理连接生命周期。
hub := websocket.NewHub()
r.GET("/ws", websocket.Handler(func(conn *websocket.Conn) {
hub.Register(conn)
defer hub.Unregister(conn)
for {
_, msg, err := conn.Conn.ReadMessage()
if err != nil { break }
// 广播给所有连接
hub.Broadcast(ws.TextMessage, msg)
}
}))
// 也支持广播 JSON
hub.BroadcastJSON(map[string]string{"event": "new_user", "name": "张三"})
自定义 Upgrader
strictUpgrader := gorilla.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return r.Header.Get("Origin") == "https://yourdomain.com"
},
}
r.GET("/ws", websocket.HandlerWithUpgrader(handler, strictUpgrader))
CheckOrigin 放通所有 origin,生产环境请务必替换为严格的白名单检查。
线程安全
Conn.WriteJSON 和 Conn.WriteSafeMessage 内部加锁,支持多 goroutine 并发写同一连接。读操作仍需单
goroutine 串行。
熔断器中间件
基于滑动窗口的熔断器(Circuit Breaker),v3.7.2 起支持按路由粒度隔离,避免单个慢接口拖垮全局。
状态机
三态自动切换:Closed(正常)→ Open(拒绝,返回 503)→ HalfOpen(试探)→ Closed(恢复)。
使用方式
# config/middleware.yaml
middleware:
global:
- recovery
- circuit_breaker
自定义配置
cfg := middleware.CircuitBreakerConfig{
WindowSize: 100, // 滑动窗口大小
ErrorThresholdPercent: 50, // 错误率阈值 (%)
CooldownDuration: 10 * time.Second,
HalfOpenMaxRequests: 5, // 半开放试探请求数
IsServerError: func(code int) bool {
return code >= 500
},
}
r.Use(middleware.CircuitBreakerWithConfig(cfg))
middleware.CircuitBreaker() 直接使用。
超时控制中间件
请求超时控制,为每个请求设置 context.WithTimeout,超时返回 504 Gateway Timeout。
使用方式
# config/middleware.yaml
middleware:
global:
- recovery
- timeout
自定义超时
// 默认 30s
r.Use(middleware.Timeout())
// 自定义 5s
r.Use(middleware.TimeoutWithDuration(5 * time.Second))
Handler 配合
func handler(c *gin.Context) {
ctx := c.Request.Context()
select {
case result := <-doWork(ctx):
c.JSON(200, result)
case <-ctx.Done():
return // 超时,中间件自动返回 504
}
}
c.Request.Context() 感知超时信号,以便及时终止数据库查询或外部 API 调用。
请求体大小限制
请求体大小限制中间件,双重保护:Content-Length 预检 + MaxBytesReader 流式保护。
使用方式
# config/middleware.yaml
middleware:
global:
- recovery
- body_limit # 默认 10MB
自定义大小
// 按字节数
r.Use(middleware.BodyLimitWithSize(5 << 20)) // 5MB
// 按字符串解析 (支持 B/KB/MB/GB)
h, _ := middleware.BodyLimitFromString("512KB")
r.Use(h)
解析工具
bytes, err := middleware.ParseBodyLimit("10MB") // 10485760
bytes, err := middleware.ParseBodyLimit("0.5GB") // 536870912
bytes, err := middleware.ParseBodyLimit("512KB") // 524288
脚手架 CLI
用一条命令生成新业务模块的 MVC 骨架,取代手工创建 controller / model / view 的重复劳动。
# 生成 app/user/ 下的 controller.go / model.go / view/ 三件套
go run ./cmd/scaffold new module user
命名规则:模块名必须以小写字母开头,只允许 a-z / 0-9 / _。生成后请在 route/ 中注册路由。
数据库迁移
框架不内置迁移工具。AutoMigrate 只适合开发期试错,生产环境推荐 pressly/goose 做版本化迁移。
go install github.com/pressly/goose/v3/cmd/goose@latest
# 目录约定:db/migrations/00001_create_users_table.sql
goose -dir db/migrations mysql "thinkgin:thinkgin@tcp(127.0.0.1:3306)/thinkgin?parseTime=true" up
详细指引见仓库中的
docs/database-migration.md。替代方案:golang-migrate/migrate、sqlc
等。
开发指南
路由规范
// route/router.go
func SetupRoutes(r *gin.Engine) {
api := r.Group("/api/v1")
{
api.GET("/users", controller.GetUsers)
api.POST("/users", controller.CreateUser)
api.PUT("/users/:id", controller.UpdateUser)
api.DELETE("/users/:id", controller.DeleteUser)
}
}
响应格式
{
"code": 200,
"data": {
"Time": "2023-02-01T10:11:41.761Z",
"data": "Hello ThinkGin!",
"name": ""
},
"msg": "ok"
}
开发最佳实践
- 目录规范:按模块组织代码结构
- 配置驱动:环境差异全部交给配置文件
- 日志规范:使用结构化字段而不是拼接字符串
- 测试覆盖:单元测试 + 集成测试
- 监控埋点:在关键业务流程写入指标
部署指南
Docker 部署(推荐)
FROM golang:1.25-alpine AS builder
WORKDIR /app
COPY . .
RUN go mod tidy && go build -o thinkgin
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/thinkgin .
COPY --from=builder /app/config ./config
CMD ["./thinkgin"]
docker build -t thinkgin:v3.1.0 .
docker run -p 8000:8000 thinkgin:v3.1.0
跨平台编译
# Linux
GOOS=linux GOARCH=amd64 go build -o thinkgin-linux
# Windows
GOOS=windows GOARCH=amd64 go build -o thinkgin.exe
# macOS
GOOS=darwin GOARCH=amd64 go build -o thinkgin-macos
Linux 后台运行
nohup ./thinkgin 1>info.log 2>&1 &
# 使用 systemd 管理
sudo systemctl enable thinkgin
sudo systemctl start thinkgin
常见问题
Go 版本过低
# 错误: go: thinkgin requires go >= 1.18
# macOS
brew install go
# 其他平台下载最新版: https://golang.org/dl/
端口占用
# Linux / macOS
lsof -ti:8000 | xargs kill -9
# Windows
netstat -ano | findstr :8000
taskkill /PID <PID> /F
网络连接问题
go env -w GOPROXY=https://goproxy.cn,direct
模块依赖问题
go clean -modcache
go mod download
go mod tidy
配置文件问题
ls -la config/
pip install yamllint
yamllint config/app.yaml
内存不足
# 调整 Go 垃圾回收
export GOGC=50
export GOMEMLIMIT=512MB # Go 1.19+
故障排查命令
go version && go env
curl -I https://goproxy.cn
netstat -tlnp | grep :8000
tail -f runtime/log/system.log
runtime/log/ 日志 → config/ YAML 语法 →
go env 环境,然后再提交 issue。