parse csv data to object(struct,protobuf,map[K]V,slice[E])
读取csv数据,转换成对象(struct,protobuf,map[K]V,slice[E]等),支持自定义解析接口,以及结构嵌套(支持2层)
// 模拟一个物品配置结构
type ItemCfg struct {
CfgId int32 `json:"CfgId,omitempty"` // 配置id
Name string `json:"Name,omitempty"` // 物品名
Detail string `json:"Detail,omitempty"` // 物品描述
Unique bool `json:"Unique,omitempty"` // 是否是不可叠加的物品
}
rows := [][]string{
{"CfgId", "Name", "Detail", "Unique", "unknownColumnTest"},
{"1", "普通物品1", "普通物品1详细信息", "false", "123"},
{"2", "普通物品2", "普通物品2详细信息", "false", "test"},
{"3", "装备3", "装备3详细信息", "true", ""},
}
m := make(map[int32]*ItemCfg)
err := ReadCsvFromDataMap(rows, m, nil)
rows := [][]string{
{"CfgId", "Name", "Detail", "Unique", "unknownColumnTest"},
{"1", "普通物品1", "普通物品1详细信息", "false", "123"},
{"2", "普通物品2", "普通物品2详细信息", "false", "test"},
{"3", "装备3", "装备3详细信息", "true", ""},
}
s := make([]*ItemCfg, 0)
s,_ = ReadCsvFromDataSlice(rows, s, nil)
type Settings struct {
ImageQuality int
Volume int
Language string
}
rows := [][]string{
{"Key", "Value", "comment"},
{"ImageQuality", "100", "画质设置"},
{"Volume", "80", "音量设置"},
{"Language", "Simplified Chinese", "语言设置"},
}
settings := new(Settings)
err := ReadCsvFromDataObject(rows, settings, nil)
rows := [][]string{
{"CfgId", "Color", "ColorFlags"},
{"1", "Red", "Red;Green;Blue"},
{"2", "Gray", "Gray;Yellow"},
{"3", "", ""},
}
type colorCfg struct {
CfgId int32
Color Color // Color是protobuf定义的枚举
ColorFlags int32 // 颜色的组合值,如 Red | Green
}
option := DefaultCsvOption
// 注册颜色枚举的自定义解析接口,csv中可以直接填写颜色对应的字符串
option.RegisterConverterByType(reflect.TypeOf(Color(0)), func(obj any, columnName, fieldStr string) any {
if colorValue, ok := Color_value["Color_"+fieldStr]; ok {
return Color(colorValue)
}
return Color(0)
})
// 注册列名对应的解析接口
// 这里的ColorFlags列演示了一种特殊需求: 颜色的组合值用更易读的方式在csv中填写
option.RegisterConverterByColumnName("ColorFlags", func(obj any, columnName, fieldStr string) any {
colorStrSlice := strings.Split(fieldStr, ";")
flags := int32(0)
for _, colorStr := range colorStrSlice {
if colorValue, ok := Color_value["Color_"+colorStr]; ok && colorValue > 0 {
flags |= 1 << (colorValue - 1)
}
}
return flags
})
m := make(map[int]*colorCfg)
err := ReadCsvFromDataMap(rows, m, &option)
详见csv_test.go里的TestNestStruct用例
游戏项目中经常使用csv作为配置文件,并需要支持热更新(服务器不重启的情况下,重新加载配置数据)
可参考gserver中的配置数据的使用方式(https://github.com/fish-tennis/gserver/tree/main/cfg)