# xlgo Web Framework
xlgo 是一个基于 Go + Gin 的轻量级 Web 开发框架,提供了完整的后端开发基础设施,包括配置管理、数据库访问、缓存、认证、日志、文件存储等常用功能。
## 框架特性
- **配置管理** - 支持 YAML 配置文件,环境变量覆盖,配置热更新
- **数据库** - MySQL + GORM,支持自动迁移、重试机制、连接池、读写分离
- **缓存** - Redis 缓存,支持分布式缓存、键前缀、TTL,SCAN 优化
- **认证** - JWT 认证,支持 Token 黑名单、刷新机制
- **日志** - 分级日志(API、数据库),日志轮转
- **中间件** - CORS、限流、日志、认证、CSRF 防护
- **文件存储** - 本地存储 + 阿里云 OSS 支持
- **实时通信** - SSE 流式响应 + WebSocket 支持
- **定时任务** - 内置任务调度器
- **验证器** - 请求参数验证,支持自定义错误消息
- **错误处理** - 统一错误码体系
- **CLI 工具** - 脚手架工具,快速创建项目和代码
## 快速开始
### 1. 安装
```bash
# 安装脚手架工具
go install github.com/EthanCodeCraft/xlgo-core/cmd/xlgo@latest
# 创建新项目
xlgo new myproject
# 进入目录
cd myproject
# 安装依赖
go mod tidy
```
### 2. 创建配置文件 config.yaml
```yaml
server:
port: 8080
mode: development
database:
host: localhost
port: 3306
user: root
password: your_password
name: your_database
max_idle_conns: 10
max_open_conns: 100
redis:
host: localhost
port: 6379
password: ""
db: 0
jwt:
secret: your_jwt_secret_key
expire: 86400
storage:
driver: local
local:
path: ./public
base_url: http://localhost:8080/public
log:
dir: ./logs
max_size: 100
max_backups: 30
max_age: 30
compress: true
```
### 3. 运行项目
```bash
go run main.go
```
访问 http://localhost:8080/health 检查服务状态。
---
## 核心功能
### 配置管理
```go
// 加载配置
cfg, err := config.Load("./config.yaml")
// 获取配置
cfg := config.Get()
serverPort := cfg.Server.Port
// 配置热更新
cfg, err := config.LoadWithWatch("./config.yaml", func(newCfg *config.Config) {
log.Println("配置已更新")
})
// 注册配置变更回调
config.RegisterCallback(func(cfg *config.Config) {
// 处理配置变更
})
// 手动重新加载
config.Reload()
```
### 数据库操作
```go
// 初始化 MySQL
database.InitMySQL(cfg)
defer database.Close()
// 主从读写分离
database.InitMySQLWithReplicas(cfg, []string{
"root:pass@tcp(slave1:3306)/db",
"root:pass@tcp(slave2:3306)/db",
})
// 读操作自动路由到从库
users := database.GetReadDB().Find(&users)
// 强制使用主库
ctx := database.UseMaster(context.Background())
database.GetDBFromContext(ctx).Find(&users)
// 事务
database.Transaction(func(tx *gorm.DB) error {
return tx.Create(&user).Error
})
// 健康检查
status := database.HealthCheck()
```
### Repository 泛型 CRUD
```go
// 创建仓库
userRepo := repository.NewBaseRepo[model.User](database.GetDB())
// 基础 CRUD
user, err := userRepo.FindByID(ctx, 1)
err := userRepo.Create(ctx, &user)
err := userRepo.Update(ctx, &user)
err := userRepo.Delete(ctx, 1)
// 分页查询
result, err := userRepo.FindPage(ctx, 1, 20)
// result.Items, result.Total, result.Page, result.PageSize
// 条件查询
users, err := userRepo.FindWhere(ctx, "status = ?", 1)
// 链式查询
users, err := userRepo.NewQueryBuilder().
Where("status = ?", 1).
Order("created_at DESC").
Limit(10).
Find(ctx)
// 批量操作
err := userRepo.CreateBatch(ctx, users)
err := userRepo.DeleteBatch(ctx, []uint{1, 2, 3})
// 事务支持
err := userRepo.WithTransaction(ctx, func(txRepo *repository.BaseRepo[model.User]) error {
return txRepo.Create(ctx, &user)
})
```
### Redis 缓存
```go
// 初始化缓存
cache.Init()
// 使用缓存
ctx := context.Background()
cacheService := cache.GetCache()
// 设置缓存
cacheService.Set(ctx, "user:1", user, 10*time.Minute)
// 获取缓存
var user User
if cacheService.Get(ctx, "user:1", &user) {
// 缓存命中
}
// 删除缓存
cacheService.Delete(ctx, "user:1")
// 按模式删除(使用 SCAN 优化)
cacheService.DeleteByPattern(ctx, "user:*")
```
### JWT 认证
```go
// 生成 Token(自动包含 JTI)
token, err := jwt.GenerateToken(userID, username, "admin", "admin")
// 解析 Token
claims, err := jwt.ParseToken(tokenString)
// 使 Token 失效(使用 JTI,高效)
jwt.InvalidateToken(tokenString)
// 获取 Token 的 JTI
jti, err := jwt.GetJTI(tokenString)
```
**JWT 黑名单优化**:使用 JTI(JWT ID)替代完整 Token 存储,大幅节省 Redis 内存。
### 分布式锁
```go
// 安全加锁(返回 LockToken)
token, err := cache.NewLock(ctx, cache.KLock("order:123"), 30*time.Second)
if token != nil {
defer cache.Unlock(ctx, token) // 只有持有者能释放
// 执行业务逻辑
}
// 续期锁(长任务场景)
cache.ExtendLock(ctx, token, 30*time.Second)
// 自动续期执行
err := cache.WithLockAutoExtend(ctx, key, 30*time.Second, 10*time.Second, func() error {
// 长任务自动续期
return nil
})
```
**分布式锁安全特性**:使用 Lua 脚本 + UUID Token,只有锁的持有者才能释放。
### Redis 分布式限流
```go
// 内存限流(单实例)
r.Use(middleware.CustomRateLimit(100, time.Minute))
// Redis 分布式限流(多实例共享)
r.Use(middleware.RedisRateLimit("api_limit", 100))
r.Use(middleware.LoginRedisRateLimit()) // 登录限流
r.Use(middleware.APIRedisRateLimit()) // API 限流
```
### 请求验证
```go
type LoginRequest struct {
Username string `json:"username" label:"用户名" validate:"required,username" msg_required:"请输入用户名"`
Password string `json:"password" label:"密码" validate:"required,password" error:"密码格式不正确"`
Phone string `json:"phone" label:"手机号" validate:"omitempty,phone" msg_phone:"请输入正确的手机号"`
}
// 绑定并验证
errors, ok := validation.ShouldBindAndValidate(c, &req)
if !ok {
response.Fail(c, errors.FirstMessage())
return
}
```
**验证器支持的自定义标签**:
- `label:"中文名"` - 字段显示名称
- `error:"通用错误消息"` - 所有验证失败时显示
- `msg_required:"必填项"` - 特定规则的错误消息
- `msg_min:"最少5个字符"` - 针对 min 规则的错误消息
### 统一错误码
```go
// 使用预定义错误
response.FailWithError(c, response.ErrUserNotFound)
// 带详细信息
response.FailWithDetail(c, response.ErrPasswordWrong, "连续错误3次将锁定账户")
// 自定义错误
err := response.NewError(10001, "自定义错误")
```
**预定义错误码**:
- 用户模块:`ErrUserNotFound`, `ErrPasswordWrong`, `ErrTokenExpired` 等
- 文件模块:`ErrFileTooLarge`, `ErrFileTypeInvalid` 等
- 数据模块:`ErrDataNotFound`, `ErrDataConflict` 等
### 文件上传
```go
// 上传文件
file, err := c.FormFile("file")
path, err := storage.Upload(file, "images")
url := storage.GetURL(path)
// 上传字节数组
path, err := storage.UploadFromBytes(data, "filename.jpg", "images")
// 删除文件
err := storage.Delete(path)
// 获取文件内容
data, err := storage.Get(path)
// 检查文件是否存在
exists := storage.Exists(path)
```
### SSE 流式响应
```go
// AI 对话场景
func ChatHandler(c *gin.Context) {
ch := make(chan string)
go func() {
defer close(ch)
for _, chunk := range aiResponse {
ch <- chunk
}
}()
sse.StreamChunks(c, ch)
}
// 带消息 ID 的流式响应
sse.StreamWithID(c, "msg_123", ch)
```
### WebSocket
```go
// 简单使用
r.GET("/ws", ws.HandleFunc(func(conn *ws.Connection, message []byte) {
conn.SendText("收到: " + string(message))
}))
// 广播模式
hub := ws.NewHub()
go hub.Run()
hub.Broadcast([]byte("广播消息"))
```
### 定时任务
```go
// 每隔 5 分钟执行
cron.AddTask("cleanup", cron.Every(5*time.Minute), func(ctx context.Context) error {
return cleanupOldData()
})
// 每天凌晨 2 点执行
cron.AddTask("daily_report", cron.Daily(2, 0), generateReport)
// 每周一上午 9 点执行
cron.AddTask("weekly", cron.Weekly(time.Monday, 9, 0), weeklyTask)
// 完整 Cron 表达式
cron.AddTask("every15min", cron.ParseCron("*/15 * * * *"), doSomething)
cron.AddTask("monthly", cron.ParseCron("0 0 1 * *"), doSomething) // 每月1号
// 启动调度器
cron.Start()
defer cron.Stop()
```
### CSRF 防护
```go
// 基本使用
r.Use(middleware.CSRF())
// 获取 Token(返回给前端)
token := middleware.GetCSRFToken(c)
// 跳过指定路径
r.Use(middleware.CSRFWithSkip([]string{"/api/webhook"}))
// API 模式(双重提交 Cookie)
r.Use(middleware.DoubleSubmitCookie())
```
### 密码加密
```go
// 加密密码
hash, err := validation.HashPassword("password123")
// 验证密码
if validation.CheckPassword(hash, "password123") {
// 密码正确
}
// 带成本升级的验证
match, needUpgrade, newHash, err := validation.CheckPasswordAndUpgrade(hash, password, 12)
```
---
## 中间件
### 认证中间件
```go
// JWT 认证(必须登录)
r.Use(middleware.AuthRequired())
// 管理员权限
r.Use(middleware.AdminRequired())
// 超级管理员权限
r.Use(middleware.SuperAdminRequired())
// 员工权限
r.Use(middleware.StaffRequired())
// 任意用户(管理员或员工)
r.Use(middleware.AnyUserRequired())
// 获取用户信息
userID := middleware.GetUserID(c)
username := middleware.GetUsername(c)
userType := middleware.GetUserType(c)
```
### 限流中间件
```go
// 登录限流(每分钟 10 次)
r.POST("/login", middleware.LoginRateLimit(), handler.Login)
// 上传限流(每分钟 20 次)
r.POST("/upload", middleware.UploadRateLimit(), handler.Upload)
// 自定义限流
r.Use(middleware.CustomRateLimit(50, time.Minute))
// 停止限流器(应用关闭时)
defer middleware.StopRateLimiters()
```
---
## 响应格式
框架使用统一的响应格式:
```json
{
"code": 1,
"msg": "操作成功",
"data": {},
"request_id": "abc123"
}
```
```go
// 成功响应
response.Success(c, data)
response.SuccessWithMsg(c, "自定义消息", data)
// 失败响应
response.Fail(c, "错误消息")
// 分页响应
response.Page(c, list, total, page, pageSize)
// 错误响应
response.Unauthorized(c, "请先登录")
response.NotFound(c, "资源不存在")
response.ServerError(c, "服务器错误")
response.RateLimit(c)
```
---
## CLI 工具
```bash
# 创建新项目
xlgo new myproject
# 创建新项目并指定模块路径
xlgo new myproject --module github.com/myorg/myproject
# 生成代码
xlgo make handler user # 创建 handler/user.go
xlgo make repository user # 创建 repository/user_repository.go
xlgo make model user # 创建 model/user.go
xlgo make service user # 创建 service/user_service.go
# 显示版本
xlgo version
```
---
## 测试
框架提供完整的测试工具包:
```go
func TestUserAPI(t *testing.T) {
router := test.SetupRouter()
// 创建请求
resp := test.POST(router, "/api/v1/users").
WithJSON(map[string]any{"name": "test"}).
WithToken("xxx").
Execute()
// 断言
resp.AssertOK(t)
// 解析响应
var result map[string]any
resp.ParseJSON(&result)
}
```
---
## 目录结构
```
xlgo/
├── app.go # 应用入口
├── cache/
│ ├── cache.go # 缓存服务
│ ├── keybuilder.go # 键名前缀管理
│ └── lock.go # 分布式锁
├── cmd/
│ └── xlgo/ # CLI 脚手架
├── compress/
│ └── compress.go # Gzip/Zip 压缩解压
├── config/
│ └── config.go # 配置管理(支持热更新)
├── console/
│ └── console.go # 彩色控制台输出
├── cron/
│ └── cron.go # 定时任务调度
├── database/
│ ├── mysql.go # MySQL 连接(支持读写分离)
│ └── redis.go # Redis 连接
├── handler/
│ └── handler.go # 基础处理器(类型安全参数获取)
├── jwt/
│ └── jwt.go # JWT 工具
├── logger/
│ ├── logger.go # 日志实现
│ └── field.go # 日志字段工具
├── middleware/
│ ├── auth.go # JWT 认证中间件
│ ├── cors.go # CORS 跨域中间件
│ ├── csrf.go # CSRF 防护中间件
│ ├── logger.go # 请求日志中间件
│ ├── ratelimit.go # 限流中间件
│ ├── requestid.go # 请求ID中间件
│ └── recover.go # Panic恢复中间件
├── model/
│ └── base.go # 基础模型
├── repository/
│ └── repository.go # 基础仓库(泛型CRUD)
├── response/
│ ├── response.go # 统一响应格式
│ └── error.go # 统一错误码
├── router/
│ └── router.go # 路由注册中心(模块化/版本化)
├── sse/
│ └── sse.go # SSE 流式响应
├── storage/
│ └── storage.go # 文件存储(本地+OSS)
├── test/
│ └── test.go # 测试工具包
├── trace/
│ └── trace.go # 链路追踪
├── utils/
│ ├── random.go # 随机数生成
│ ├── strings.go # 字符串处理
│ ├── datetime.go # 时间日期
│ ├── convert.go # 类型转换
│ ├── file.go # 文件操作
│ ├── url.go # URL处理
│ ├── validator.go # 格式验证
│ ├── crypto.go # 加密编码
│ ├── http.go # HTTP客户端
│ └── uuid.go # UUID生成
├── validation/
│ ├── validator.go # 请求验证器
│ ├── password.go # 密码强度验证
│ └── hash.go # 密码加密
├── wire/
│ └── wire.go # 依赖注入
└── ws/
└── ws.go # WebSocket 支持
```
---
## 部署指南
### Docker 部署
```dockerfile
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o server .
FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata
WORKDIR /app
COPY --from=builder /app/server .
COPY --from=builder /app/config.yaml .
RUN mkdir -p /app/public /app/logs
EXPOSE 8080
CMD ["./server", "-config", "./config.yaml"]
```
```bash
docker build -t xlgo-app:latest .
docker run -d -p 8080:8080 xlgo-app:latest
```
---
## 更新日志
### v2.1.0 (2026-04-30)
- **分布式锁安全增强** - Lua 脚本 + UUID Token,只有持有者能释放锁
- **JWT 黑名单优化** - 使用 JTI 替代完整 Token,大幅节省 Redis 内存
- **HTTP Client 连接池** - Transport 初始化时创建,连接可复用
- **优雅关闭机制** - 监听系统信号,等待请求处理完成
- **Redis 分布式限流** - 滑动窗口算法,多实例共享限流状态
- **Repository 扩展** - 分页查询、链式查询、批量操作、事务支持
- **CORS 配置完善** - 支持配置文件、通配符域名
- **日志中间件增强** - 可记录请求体、慢请求警告、敏感字段过滤
- **新增测试** - cache、middleware 新增多项测试用例
### v2.0.0 (2026-04-30)
- **新增工具函数库** - 111 个实用函数(随机数、字符串、时间、转换、文件、URL、验证、加密、HTTP 客户端、UUID)
- **新增彩色控制台输出** - console 包支持 Debug/Info/Success/Warn/Error 五级彩色输出
- **新增压缩解压** - compress 包支持 Gzip/Zip 压缩解压
- **新增键名前缀管理** - cache.K() 自动添加站点前缀,解决多项目共用 Redis 冲突
- **新增分布式锁** - cache.Lock/TryLock/WithLock 完整实现
- **新增计数器** - cache.Incr/Decr/IncrBy 支持
- **新增 RequestID 中间件** - 请求追踪支持
- **新增 Recover 中间件** - Panic 恢复
- **新增类型安全参数获取** - handler.QueryInt/PathInt/FormInt 等
- **新增路由架构** - router 包支持模块化、版本化 API、中间件分组、RESTful CRUD
- **新增 AppConfig** - 站点别名、环境判断
- **CLI 工具重构** - 模块化结构,模板分离
- **单元测试覆盖** - 17 个包有测试(68%覆盖)
### v1.1.0 (2026-04-29)
- 新增配置热更新支持
- 新增数据库读写分离
- 新增 CSRF 防护中间件
- 新增 SSE 流式响应支持
- 新增 WebSocket 支持
- 新增定时任务调度器
- 新增 CLI 脚手架工具
- 新增测试工具包
- 新增统一错误码体系
- 新增密码加密工具
- 新增请求验证器(支持自定义错误消息)
- 实现 OSS 存储上传
- 优化缓存 DeleteByPattern 使用 SCAN
- 修复限流器 goroutine 泄漏问题
### v1.0.0 (2024-04)
- 初始版本发布
- 基础框架功能
- 完整示例代码
---
## 许可证
MIT License - 详见 [LICENSE](LICENSE) 文件