ini.load("config.ini")易panic,主因是路径非绝对、utf-8 bom未清除、节名含非法字符、未启用loose模式或未检查err;须用filepath.join(filepath.dir(os.executable()), "config.ini")拼绝对路径,bytes.trimprefix去bom,load时传loose:true,数值读取优先用mustint64()等带默认值方法。

用 github.com/go-ini/ini@v1.67.0 加载带 BOM 或相对路径的 INI 文件
直接 ini.Load("config.ini") 很容易 panic,尤其在 Windows 上用记事本保存的文件常带 UTF-8 BOM,或运行时工作目录不固定。错误现象是 error 为 nil,但后续调用 cfg.Section("xxx").Key("y").String() 崩溃。
- 路径必须转绝对路径:用
filepath.Abs("config.ini")或基于二进制位置拼接,例如execDir, _ := filepath.Dir(os.Executable()); iniPath := filepath.Join(execDir, "config.ini") - BOM 必须手动清除:读取后用
bytes.TrimPrefix(content, []byte("\xef\xbb\xbf")),再传给ini.LoadSources() - 加载时启用宽松模式:传
ini.LoadOptions{Loose: true},避免节不存在就 panic;否则必须先cfg.HasSection("db")
处理嵌套节名(如 [database.mysql])和跨节变量引用
go-ini 不解析点号语义,[database.mysql] 就是个独立节名,不是 database 下的子节。想复用配置得靠插值,但默认关闭。
- 启用插值必须加两个选项:
AllowPythonInterpolation: true和Insensitive: true(大小写敏感会导致%(HOST)s匹配失败) - 插值只支持同节或
[DEFAULT]节里的 key,[mysql]里写host = %(common_host)s是无效的,除非common_host在[DEFAULT]或同一节中 - 节名含点号时,调用必须完全匹配:
cfg.Section("database.mysql")不能简写成cfg.Section("database").Section("mysql")
安全读取数值与带单位字段(如 timeout = 30s)
Key().Int64() 对 timeout = 30s 这种值会静默返回 0,不报错也不提示——这是最危险的坑。
- 数字类型一律用
MustInt64(30)、MustBool(false),它会在解析失败时返回默认值,且不会 panic - 带单位的字段(
timeout、size)必须读成字符串:cfg.Section("server").Key("timeout").String(),再手动用time.ParseDuration()或正则提取 -
String()不 trim 空格,若配置写成host = 127.0.0.1,结果就是带空格字符串,需strings.TrimSpace()
并发读写与原子写入 INI 文件
go-ini 的 *ini.File 实例**不是并发安全的**,多 goroutine 同时调用 cfg.Section("x").Key("y").SetValue("z") 可能导致数据错乱;写入也不保证原子性。
- 读操作可共享一个
*ini.File,但写操作必须加互斥锁(sync.RWMutex),或每次写前重新Load()+ 修改 +Save() - 写入前建议先备份原文件:
os.Rename("config.ini", "config.ini.bak"),再cfg.SaveTo("config.ini"),避免写到一半崩溃丢配置 - 不要用
cfg.Section("").Key("xxx").SetValue("yyy")直接改全局键——它只影响内存,必须显式SaveTo()才落盘
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











