JSON更稳,因Go原生支持嵌套结构解析与字段映射;CSV轻量易编辑但需手动处理类型和引用,中小项目常用CSV+反射加载,大项目倾向JSON或Protobuf。

配置表用 JSON 还是 CSV?Go 里选哪个更稳
JSON 更适合嵌套结构(比如技能树、装备套装),Go 原生 json.Unmarshal 支持好,字段名映射清晰;CSV 更轻量、易被策划编辑,但需要自己处理类型转换和引用关系(比如“职业ID”指向另一张表)。实际项目里,中小规模游戏常用 CSV + Go 结构体反射加载,大项目倾向 JSON 或 Protocol Buffers 配合生成代码。
别直接用 encoding/csv 读原始切片——容易漏掉空行、类型错位。推荐封装一层:先按首行当 header 构建 map[string]int 索引,再逐行 strconv.Atoi/strconv.ParseFloat 转换,失败时带行列号 panic,方便定位配置错误。
如何让配置表热重载不崩 goroutine
热重载不是简单 reload 文件,关键是原子替换内存中的配置实例,避免正在战斗的怪物读到半新半旧的掉落表。核心是用 sync.RWMutex 包裹全局配置指针,写时加写锁,读时加读锁。
- 重载函数里先解析新数据到临时变量,校验通过后再
mutex.Lock()→ 替换指针 →mutex.Unlock() - 所有业务代码读配置必须用
mutex.RLock()+ defermutex.RUnlock(),不能缓存旧指针 - 如果用
map存配置(如map[int]*ItemConfig),重载时整个 map 替换,别试图单条更新——并发写 map 会 panic
配置 ID 冲突或缺失怎么快速发现
运行时报 “nil pointer dereference” 很可能是因为策划填错了 ID,查表返回 nil。与其等线上 crash,不如在加载阶段就做完整性检查。
立即学习“go语言免费学习笔记(深入)”;
常见检查点:
- 主键字段(如
ID)是否重复:遍历后用map[int]bool记录,第二次见到就报错 - 外键字段(如
RequireJobID)是否在对应表中存在:加载完所有表后,统一扫一遍外键字段值,不在目标 map 的 key 里就 warn - 数值字段是否越界(如
HP < 0或Level > 100):在结构体上加自定义 tag,比如validate:"min=1,max=99",用反射跑校验
为什么用 embed 不用 filepath.WalkDir 加载配置
开发期用 filepath.WalkDir 没问题,但上线后配置文件被删、路径错、权限不足都会导致启动失败。Go 1.16+ 的 embed 把配置文件编译进二进制,启动零 IO 依赖,也杜绝了运行时篡改风险。
用法很简单:
- 加
//go:embed configs/*.json注释 - 声明
var configFS embed.FS - 用
configFS.ReadFile("configs/item.json")读取
**/*.json 不行),多级目录得手动列或写构建脚本预合并。
配置加载最麻烦的从来不是语法,而是跨环境一致性——本地能跑的配置,到测试服因大小写、BOM、换行符差异就解析失败。建议 CI 阶段加一步 file -i *.csv 检查编码,用 dos2unix 统一行尾,再进 Go 加载流程。



















