logo
0
0
WeChat Login
refactor: 全面代码审查与优化

ThinkGo - Go Web 基础框架

基于 DarkiT-GIN 的企业级 Go Web 开发框架,提供开箱即用的开发体验。

特性

  • 🚀 快速开发 - 基于 DarkiT-GIN,自动路由注册,约定优于配置
  • 🏗️ 清晰架构 - Controller → Service → Repository 三层架构
  • 🔐 JWT 认证 - 内置 JWT 认证授权系统
  • 🌐 国际化 - 多语言支持(i18n)
  • 定时任务 - 集成 darkit-cron 任务调度
  • 📡 事件总线 - darkit-eventbus 异步事件处理
  • ⚙️ 配置管理 - darkit-sysconf,支持 YAML + 环境变量
  • 📝 统一响应 - 标准化 API 响应格式
  • 🗄️ 多数据库 - 支持 SQLite/MySQL/PostgreSQL
  • 🔧 泛型仓库 - 通用 CRUD 操作,减少样板代码
  • 增强验证 - 自定义验证器(手机号、强密码等)
  • 🚨 错误规范 - 统一业务错误处理与国际化
  • ❤️ 健康检查 - Kubernetes liveness/readiness 探针
  • 🛡️ 中间件套件 - 限流、CORS、Request ID、日志、恢复
  • 💾 缓存抽象 - 统一缓存接口,支持内存/Redis
  • 📋 审计日志 - 基于事件总线的操作审计

快速开始

安装依赖

go mod tidy

配置

编辑 config/app.yaml,配置数据库、JWT 等参数。

运行

# 编译并运行 make run # 或直接运行 go run cmd/server/main.go -config config

开发模式(热重载)

# 安装 air go install github.com/air-verse/air@latest # 启动热重载 make dev

项目结构

├── cmd/server/ # 程序入口 ├── app/ # 应用核心 │ ├── api/ # API 应用 │ │ ├── controller/ # 控制器 │ │ └── route/ # 路由 │ ├── middleware/ # 全局中间件 │ ├── model/ # 数据模型 │ ├── repository/ # 数据访问层 │ ├── service/ # 业务逻辑层 │ └── facade/ # 门面模式 ├── bootstrap/ # 应用启动引导 ├── config/ # 配置文件 ├── pkg/ # 公共代码 ├── scheduler/ # 定时任务 ├── event/ # 事件总线 ├── public/ # 静态资源 └── runtime/ # 运行时目录

API 示例

用户注册

curl -X POST http://localhost:8080/api/auth/register \ -H "Content-Type: application/json" \ -d '{ "username": "admin", "email": "admin@example.com", "password": "123456" }'

用户登录

curl -X POST http://localhost:8080/api/auth/login \ -H "Content-Type: application/json" \ -d '{ "username": "admin", "password": "123456" }'

获取用户列表(需认证)

curl -X GET http://localhost:8080/api/users/list?page=1&page_size=10 \ -H "Authorization: Bearer <your-token>"

开发指南

添加新模块

  1. 创建模型 app/model/xxx.go
  2. 创建仓库 app/repository/xxx.go
  3. 创建服务 app/service/xxx.go
  4. 创建控制器 app/api/controller/xxx.go
  5. app/api/route/router.go 注册路由

自动路由注册

控制器方法命名遵循约定:

  • GetXxxGET /xxx
  • PostXxxPOST /xxx
  • PutXxxPUT /xxx
  • DeleteXxxDELETE /xxx
  • GetXxxRegex → 正则路由(需配置)

错误处理策略

本框架采用分层错误处理机制:

Service 层(业务错误)

使用 errors.New() 或自定义错误变量:

var ( ErrUserNotFound = errors.New("用户不存在") ErrUserExists = errors.New("用户已存在") ) func (s *userService) GetByID(ctx context.Context, id uint) (*model.User, error) { user, err := s.repo.FindByID(ctx, id) if err != nil { return nil, ErrUserNotFound // 返回业务错误 } return user, nil }

API 层(HTTP 响应)

在控制器中映射业务错误到 HTTP 错误码:

import "github.com/darkit/thinkgo/pkg/response" func (c *UserController) GetByID(ctx *gin.Context) { user, err := facade.User().GetByID(ctx, id) if err != nil { if err == service.ErrUserNotFound { ctx.Error(response.CodeUserNotFound, "用户不存在") return } ctx.Error(response.CodeInternalError, "服务器错误") return } ctx.Success(user) }

错误码定义(pkg/response/errors.go

错误码常量说明
0CodeSuccess成功
40000CodeBadRequest请求参数错误
40100CodeUnauthorized未授权
40300CodeForbidden禁止访问
40400CodeNotFound资源不存在
42200CodeValidationError参数校验失败
50000CodeInternalError服务器内部错误
60001CodeUserNotFound用户不存在
60002CodeUserExists用户已存在
60003CodePasswordError密码错误

扩展业务错误码:新模块按 6xxxx 范围分配(如订单模块 610xx,商品模块 620xx)

新功能指南

1. 通用泛型仓库

使用泛型仓库减少 50%+ 的样板代码:

// 定义仓库接口 type UserRepository interface { repository.GenericRepository[model.User] FindByUsername(ctx context.Context, username string) (*model.User, error) } // 实现仓库 type userRepository struct { repository.GenericRepository[model.User] } func NewUserRepository(db *gorm.DB) UserRepository { return &userRepository{ GenericRepository: repository.NewGenericRepository[model.User](db), } }

2. 自定义验证器

支持 5 个开箱即用的验证器:

type RegisterRequest struct { Username string `json:"username" binding:"required,username"` // 3-20位,字母开头 Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required,strongPassword"` // 至少8位,大小写+数字 Mobile string `json:"mobile" binding:"omitempty,mobile"` // 中国大陆手机号 IDCard string `json:"id_card" binding:"omitempty,idCard"` // 18位身份证 Website string `json:"website" binding:"omitempty,httpUrl"` // HTTP/HTTPS URL }

3. 统一错误处理

使用 BusinessError 实现错误规范化:

import "github.com/darkit/thinkgo/pkg/errors" // Service 层返回业务错误 if user == nil { return nil, errors.ErrUserNotFound } // Controller 层处理错误 var bizErr *errors.BusinessError if errors.As(err, &bizErr) { ctx.Error(bizErr.Code, ctx.T(bizErr.I18nKey)) return }

4. 健康检查

Kubernetes 探针配置:

# deployment.yaml livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 10 periodSeconds: 30 readinessProbe: httpGet: path: /health/ready port: 8080 initialDelaySeconds: 5 periodSeconds: 10

5. 中间件配置

全局中间件已自动注册,可选配置:

// 启用请求限流(在 bootstrap/app.go 中取消注释) router.Use(middleware.RateLimitMiddlewareSimple(100)) // 每秒100个请求 // 自定义 CORS 配置 router.Use(middleware.CORSMiddleware(&middleware.CORSConfig{ AllowOrigins: []string{"https://example.com"}, AllowMethods: []string{"GET", "POST", "PUT", "DELETE"}, AllowCredentials: true, }))

6. 缓存使用

统一缓存接口,无缝切换实现:

// 开发环境:内存缓存 cache := cache.NewMemoryCache() // 生产环境:Redis 缓存 client := redis.NewClient(&redis.Options{ Addr: "localhost:6379", }) cache := cache.NewRedisCache(client) // 使用缓存 data, err := cache.Get(ctx, "user:1") if errors.Is(err, cache.ErrCacheMiss) { // 缓存未命中,查询数据库 user := queryDatabase() cache.Set(ctx, "user:1", userData, 5*time.Minute) }

7. 审计日志

发布审计事件:

import "github.com/darkit/thinkgo/event/handlers" // 在 Service 层发布审计事件 eventBus.Publish("user.login", &handlers.AuditEntry{ EventName: "user.login", UserID: user.ID, Username: user.Username, Action: "login", Resource: "user", IP: ctx.ClientIP(), RequestID: middleware.GetRequestID(ctx), Timestamp: time.Now(), Result: "success", })

技术栈

License

MIT