基于 DarkiT-GIN 的企业级 Go Web 开发框架,提供开箱即用的开发体验。
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/ # 运行时目录
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>"
app/model/xxx.goapp/repository/xxx.goapp/service/xxx.goapp/api/controller/xxx.goapp/api/route/router.go 注册路由控制器方法命名遵循约定:
GetXxx → GET /xxxPostXxx → POST /xxxPutXxx → PUT /xxxDeleteXxx → DELETE /xxxGetXxxRegex → 正则路由(需配置)本框架采用分层错误处理机制:
使用 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
}
在控制器中映射业务错误到 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)
}
| 错误码 | 常量 | 说明 |
|---|---|---|
| 0 | CodeSuccess | 成功 |
| 40000 | CodeBadRequest | 请求参数错误 |
| 40100 | CodeUnauthorized | 未授权 |
| 40300 | CodeForbidden | 禁止访问 |
| 40400 | CodeNotFound | 资源不存在 |
| 42200 | CodeValidationError | 参数校验失败 |
| 50000 | CodeInternalError | 服务器内部错误 |
| 60001 | CodeUserNotFound | 用户不存在 |
| 60002 | CodeUserExists | 用户已存在 |
| 60003 | CodePasswordError | 密码错误 |
扩展业务错误码:新模块按 6xxxx 范围分配(如订单模块 610xx,商品模块 620xx)
使用泛型仓库减少 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),
}
}
支持 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
}
使用 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
}
Kubernetes 探针配置:
# deployment.yaml
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
全局中间件已自动注册,可选配置:
// 启用请求限流(在 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,
}))
统一缓存接口,无缝切换实现:
// 开发环境:内存缓存
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)
}
发布审计事件:
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",
})
MIT