Revel 通过命令行参数或环境变量指定运行环境:revel run myapp dev 或 revel run myapp prod,或设 REVEL_RUNMODE=prod revel run myapp;app.conf 中的 run.mode 不生效,配置按 app.conf 基线 + dev.conf/prod.conf 覆盖方式加载。

revel run 时如何指定运行环境(dev/prod)
Revel 默认启动为 dev 模式,但不会自动读取 conf/app.conf 中的 run.mode 配置——这个字段仅作文档参考,实际生效靠命令行参数或环境变量。
必须显式传参才能切环境:
-
revel run myapp dev:强制 dev 模式(启用热重载、详细错误页、conf/dev.conf覆盖项) -
revel run myapp prod:强制 prod 模式(禁用热重载、隐藏错误详情、加载conf/prod.conf) - 也可用环境变量:
REVEL_RUNMODE=prod revel run myapp,效果等同于加prod参数
常见错误:只改了 app.conf 里的 run.mode = prod 却没在命令行加 prod,结果仍是 dev 行为——Revel 不会解析该配置项来决定运行模式。
多环境配置文件怎么组织与加载
Revel 的配置加载是「叠加式」而非「替换式」:app.conf 是基线,dev.conf/prod.conf 是增量补丁。它不支持嵌套环境(如 staging),也不支持按目录分阶(如 conf/base/ + conf/prod/db.conf)。
正确组织方式:
- 所有配置写在
conf/app.conf(例如app.name,http.port,session.cookie.secure) - 环境特有值写在
conf/dev.conf(如db.url = "root@/dev")或conf/prod.conf(如db.url = "user:pass@tcp(10.0.1.5:3306)/prod") - 文件内键名必须完全一致,Revel 会用后加载的值覆盖前者的同名键
注意:conf/prod.conf 不会自动加密或隐藏,敏感字段(如数据库密码)仍需通过环境变量注入,例如在 prod.conf 中写 db.password = ${DB_PASSWORD},再启动前设 DB_PASSWORD=xxx。
为什么 revel.Config.String("xxx") 在 init() 里拿不到 prod 值
因为 Revel 的配置加载发生在 revel.Init() 内部,而 app/init.go 的包级 init() 函数执行早于配置加载——此时 revel.Config 还是空的。
正确时机只有两个:
- 在
revel.AppInit()函数中访问(此时配置已加载完成) - 在 filter 或 controller 中访问(确保请求上下文已建立)
典型错误写法:
var dbURL = revel.Config.String("db.url") // panic: Config not loaded yet
应改为:
func AppInit() {<br> dbURL := revel.Config.String("db.url") // ✅ 安全<br> // 初始化 DB 实例<br>}
跨项目复用配置结构的可行路径
Revel 原生不支持配置继承或模块化导入,但可通过以下方式规避重复维护:
- 把公共配置抽成 shell 脚本或 Makefile,在 CI/CD 中用
sed或envsubst注入变量后生成最终app.conf - 用 Go 工具链预处理:写个
genconf/main.go,读取templates/app.conf.tmpl和envs/prod.yaml,渲染出目标配置 - 放弃
conf/*.conf,改用revel.LoadConfig("config.yaml")手动加载结构化配置(需自行处理环境切换逻辑)
最易踩坑的是硬编码路径拼接——比如在 init() 里用 revel.BasePath + "/conf/db.conf",但 Revel 的 BasePath 在不同启动方式下可能指向 GOPATH/src 或模块根目录,不可靠。始终优先走 revel.Config 接口。











