不能只用os.Getenv读环境变量,因其缺乏类型安全、易漏改导致panic、fallback逻辑分散、测试污染全局状态;gcfg通过统一加载、优先级合并、结构体tag解析,实现类型安全与环境隔离。

Fiber 本身不解析环境变量,必须靠外部配置方案加载后手动注入——直接读 os.Getenv 只适合简单场景,复杂项目必须用 gcfg 统一管理,否则环境覆盖混乱、本地/生产行为不一致。
为什么不能只用 os.Getenv 读环境变量
硬编码 os.Getenv("DB_HOST") 看似简单,但会快速失控:
- 所有地方散落
os.Getenv调用,改名或加默认值时漏改一处就 panic - 没有类型安全:
os.Getenv("PORT")返回string,你得自己strconv.Atoi,出错不报位置 - 无法 fallback:想“本地用
localhost,生产读DB_HOST”,就得写 if-else 分支,越积越多 - 测试困难:每个 test case 都要
os.Setenv+defer os.Unsetenv,极易污染全局状态
用 gcfg 统一加载环境变量和配置文件
gcfg 把环境变量、配置文件、命令行参数全归为“配置源”,按优先级合并,天然支持环境隔离。它不是替代 os.Getenv,而是封装它。
- 默认自动读取
GF_*前缀的环境变量(如GF_DATABASE_HOST→database.host) - 同时加载
config.yaml,环境变量值会覆盖配置文件同名字段(优先级更高) - 结构体字段用
gcfgtag(如Host string `gcfg:"host,default=localhost"`),不用手写默认逻辑 - 启动时一次性加载,后续所有
g.Cfg().Get("database.host")都是已解析好、带类型的值
示例:
type Config struct {
Database struct {
Host string `gcfg:"host,default=localhost"`
Port int `gcfg:"port,default=5432"`
} `gcfg:"database"`
}然后 g.Cfg().MustGet("database.port").Int() 直接得 int,无需转换。
GF_GCFG_ENV 和 FIBER_ENV 的区别与配合
这两个变量常被混用,但作用完全不同:
-
GF_GCFG_ENV是gcfg的运行时环境标识(如dev/prod),决定加载哪个配置文件(config.dev.yaml还是config.prod.yaml) -
FIBER_ENV是 Fiber 框架自己的变量,仅影响日志级别、错误堆栈是否暴露等运行时行为,**不参与配置加载** - 必须显式设置
GF_GCFG_ENV=prod才能触发gcfg加载生产配置;只设FIBER_ENV=prod对配置无任何影响 - 容器部署时推荐同时设两个:
GF_GCFG_ENV=staging FIBER_ENV=staging,保持语义一致
开发阶段怎么快速切换环境配置
别靠改环境变量来回重启,效率低还容易忘:
- 用
gcfg的AddPath设置多级路径,按顺序查找:./configs/staging/→./configs/common/,避免重复写相同字段 - 本地开发时,用
--gf.gcfg.env=dev命令行参数覆盖环境,比export GF_GCFG_ENV=dev更轻量 - IDE 启动配置里直接填 Environment variables,比如 GoLand 的 Run Configuration → Environment variables 栏写
GF_GCFG_ENV=local - 切记:
gcfg不会自动监听GF_GCFG_ENV变更,改了必须重启进程,这点和文件热重载不同
最易忽略的是:环境变量名大小写敏感,gf_gcfg_env 或 GF-gcfg-env 全无效,必须严格用 GF_GCFG_ENV。

















