Kratos配置需显式控制source顺序:从左到右合并,base.yaml(左)、环境yaml(中)、env.NewSource()(右),环境变量须全大写展平,YAML不支持${}占位符,struct tag必须严格匹配。

Kratos 本身不提供「多环境配置文件自动切换」的魔法能力,所有环境隔离都靠你显式控制 config.WithSource 的顺序和内容。没配对源、顺序写反、环境变量名大小写错,都会导致配置读不出来或被意外覆盖。
config.WithSource 的加载顺序决定优先级
Kratos 配置是「从左到右合并」,不是「覆盖后重载」。靠前的源里有的 key,后面的同名 key 就不会生效。
-
file.NewSource("configs/base.yaml")放最左:放公共字段(如日志级别、服务名) -
file.NewSource(fmt.Sprintf("configs/%s.yaml", env))放中间:放环境专属字段(如 DB 地址、超时时间) -
env.NewSource()放最右:放最高优的运行时覆盖(如密码、密钥),但注意它只读大写键
错误示例:env.NewSource(), file.NewSource("configs/prod.yaml") —— 这样 prod.yaml 里的字段永远无法生效,因为环境变量没设时值为空,但 Kratos 不会 fallback 到下一个源。
YAML 文件里不能写 ${ENV} 占位符
Kratos 的 yaml 解析器不支持变量展开。像 password: ${DB_PASSWORD} 这种写法完全无效,解析出来就是字面量字符串 ${DB_PASSWORD}。
- 正确做法:YAML 里留空或写占位符(如
password: "xxx"),靠env.NewSource()动态注入 - 敏感字段必须走环境变量,且变量名要全大写、用下划线分隔(
DB_PASSWORD→ YAML 中对应字段应为password) - 嵌套结构(如
server.port)必须展平为SERVER_PORT,否则env.NewSource()根本读不到
命令行参数 -env 和 -conf 的实际作用
kratos run 自带的 -env 只影响构建阶段(比如生成 wire_gen.go 时),**运行时完全不生效**。真正起作用的是你自己在 main.go 里解析的 flag。
- 定义 flag:
flag.StringVar(&env, "env", "dev", "environment name") - 构造源时拼路径:
file.NewSource(fmt.Sprintf("configs/%s.yaml", env)) - 启动时指定:
./app -env prod或./app -conf configs/prod.yaml - 别把
-conf和-env混用:前者直接加载单个文件,后者只是帮你拼路径,两者逻辑互斥
容易被忽略的 struct tag 和大小写匹配
YAML 键名和 Go 结构体字段之间不是靠名字推断,而是严格依赖 yaml:"xxx" tag。哪怕只差一个下划线或大小写,字段就会是零值。
- YAML 写
http_port: 8080,结构体字段必须带yaml:"http_port",且不能写成HttpPort或HTTPPort(除非 tag 显式声明) - 用
proto定义配置时(如conf/conf.proto),生成的 Go 代码默认使用snake_case转CamelCase规则,但 YAML 仍需按原始 proto 字段名写(小写+下划线) - 调试时可加一行
log.Println(config)打印最终解析结果,比猜更可靠











