ini.Load() panic 主因是路径错误或UTF-8 BOM残留,节名仅允许字母、数字、下划线和点号;strict mode下Section()遇不存在节直接panic,应先HasSection()或用Must方法;Key().Int64()等静默失败需改用MustInt64()并传默认值。

ini.Load() 一调就 panic,八成是路径或编码问题
不是配置写错了,而是加载阶段就崩了。最常见两个错误:open config.ini: no such file or directory 和 line 5: invalid section name "db:port"——前者说明路径没拼对,后者说明节名含非法字符(冒号、短横线、前导空格)或文件带 UTF-8 BOM。
- 路径必须绝对:传
"config.ini"会按os.Getwd()解析,但线上二进制启动目录和配置文件通常不在一起;改用filepath.Join(filepath.Dir(os.Args[0]), "config.ini") - BOM 必须手动清除:UTF-8 文件若带
\xef\xbb\xbf,ini.Load()不会自动 strip;先os.ReadFile(),再bytes.TrimPrefix(data, []byte("\xef\xbb\xbf")),最后用ini.LoadSources() - 节名只允许字母、数字、下划线、点号;
[db.port]合法,[db:port]、[db-port]、[ db ](前导空格)都会报错
cfg.Section("xxx") 直接 panic?strict mode 在作怪
Section() 默认是“获取”,不是“获取或创建”。一旦节不存在,strict mode 下直接 panic,很多人误以为它会 fallback 或自动建空节。
- 安全做法:先用
cfg.HasSection("db")判断,或改用cfg.Section("log").Key("level").MustString("info")——MustXxx()方法内部会自动创建空节,不 panic - 想全局禁 strict:加载时加选项
ini.LoadOptions{Loose: true} - 注意:
MustString("default")的默认值只在 key 不存在时生效;如果 key 存在但值为空字符串,它仍返回空串,不会 fallback
嵌套节名如 "database.mysql" 不是嵌套,只是字符串
go-ini 不做递归挂载,也不支持继承。[database.mysql] 和 [database] 完全无关,它把整个 database.mysql 当作一个独立节名字符串处理——这点和 Python 的 configparser 行为不同,容易误解。
- 动态选节得拼字符串:
env := "prod"→cfg.Section("redis." + env),而不是指望cfg.Section("redis").Section(env) - 点号只是命名约定:
cfg.Section("database.mysql")和cfg.Section("database/mysql")是两个完全不同的节 - 没有内置 fallback:想复用
host,得手动读cfg.Section("database").Key("host").String(),再 fallback 到cfg.Section("database.prod").Key("host").String()
Key().Int64() 返回 0?别信 String(),优先用 Must 方法
Key().String() 返回空字符串,Key().Int64() 解析失败时返回 0 —— 这种静默失败对数字/布尔类型极其危险。比如配置写了 timeout = 30s,.Int64() 直接返回 0,程序照常跑但逻辑错乱。
立即学习“go语言免费学习笔记(深入)”;
- 一律用
MustInt64(30)、MustBool(true)等带Must前缀的方法,并传入合理默认值 - 含单位的字段(如
timeout = 5s)别依赖自动转,应先.String(),再用time.ParseDuration() -
.String()不 trim 空格,需要干净值就得自己strings.TrimSpace()
err 就直接用 cfg——这些地方一漏,后面所有解析都白搭。


















