go-admin和ruoyi-go是带完整生命周期的独立服务,非gin插件;必须克隆完整项目、执行migrate初始化数据库、严格按预设路由组注册接口,否则易因配置缺失或执行顺序错误导致500或panic。

直接用 go-admin 或 RuoYi-Go 这类现成框架,90% 的人会卡在初始化阶段——不是代码写错,而是没搞清它们和普通 Gin 项目的本质区别:它们不是“插件”,而是带完整生命周期的独立服务。
别把 GoAdmin 当 Gin 插件来用
GoAdmin 不是调个 router.Use() 就能挂上的中间件。它自带 CLI 工具、预设路由组、Casbin 策略加载时机、数据库迁移流程,甚至要求你必须从它的仓库克隆完整项目结构。强行在已有 Gin 项目里 go get 然后调 app.Initialize(),大概率触发 panic: runtime error: invalid memory address or nil pointer dereference,因为配置没加载、DB 实例为空、JWT 密钥未注入。
- 启动前必须执行
./go-admin migrate -c config/settings.yml,否则sys_user表不存在,登录直接 500 -
config/settings.yml中的database.dsn必须是标准格式:root:password@tcp(127.0.0.1:3306)/go_admin?charset=utf8mb4&parseTime=True&loc=Local,漏掉&或写成&会导致连接失败 - 新增业务接口不能写
r.POST("/city", handler),必须注册进routerCheckRole切片,并绑定到v1.Group("/admin")下,否则 JWT 和 RBAC 中间件不生效
用 gin + gorm 自搭才是真可控
gin + gorm 不是“选框架”,是选控制权。token 怎么签、权限怎么查、菜单怎么加载,全在你写的几行代码里。出问题时不用猜框架哪层吞了错误,直接看三处:
-
exp字段必须是int64秒级时间戳:jwt.MapClaims{"exp": time.Now().Add(time.Hour).Unix()},写成毫秒或字符串就 401 - JWT 中间件默认从
Authorization头取值,格式必须是Bearer xxx:少空格(Bearerxxx)、多空格(Bearer xxx)、写成Token xxx全部失败 - 中间件必须用
router.Use()全局注册;如果只在v1 := router.Group("/api/v1")下加v1.Use(jwtauth.Middleware()),那未分组的/api/users就绕过鉴权暴露
关联查询和结构体定义要防 N+1 和 panic
GORM 默认不预加载关联数据。比如查用户列表并显示角色名,写 db.Find(&users) 再循环 user.Role.Name,就会触发 N 次 SQL 查询。更危险的是结构体嵌套:不要写 type User struct { Role Role },而要用指针 + 显式 tag:Role *Role `gorm:"foreignKey:RoleID"`,否则 JSON 序列化时可能无限递归或 panic。
- 查列表带关联字段,必须用
Preload("Role")一次性加载 - 模型字段 tag 必须对齐 GORM v2,比如
gorm:"column:username";若主项目用 GORM v1 或自定义 json tag,启动时可能忽略字段或 panic - 如果集成 admin 前端模块(如 RuoYi-Go 的 Vue 部分),别让它起独立 HTTP server,否则你的 JWT 中间件、日志埋点全失效
最常被忽略的一点:所有现成框架的“自动初始化”都依赖精确的配置路径和执行顺序。哪怕只是改了个 settings.yml 的位置,或把 migrate 命令跑在 go run main.go 之前,整个后台就起不来——它不会报错,只会静默卡住或返回 500。











