Go中基于JSON文件实现持久化map[string]string的问题
在Go中基于JSON文件实现字符串到UUID的持久化映射
核心问题说明
jsonfile.Read 方法设计为只读访问,回调内的修改不会被持久化,也不允许在Read流程中调用Write操作。正确的做法是先通过Read检查键是否存在,若不存在则通过Write方法修改并持久化数据。
另外需要注意:你提供的JSON是顶层键值对结构,但当前Data结构体嵌套了identifiers字段,两者不匹配,会导致读取失败。下面给出两种适配方案。
方案1:直接使用顶层map[string]string(匹配你提供的JSON格式)
这种方式无需嵌套结构体,直接将JSON文件作为map[string]string处理:
package main import ( "fmt" "log" "os" "crawshaw.dev/jsonfile" "github.com/google/uuid" ) func GetOrCreateUUID(key string) (string, error) { // 加载或创建JSON文件 db, err := jsonfile.Load[map[string]string]("resolver.json") if os.IsNotExist(err) { db, err = jsonfile.New[map[string]string]("resolver.json") } if err != nil { return "", err } // 先读取检查键是否存在 var existingUUID string keyExists := false err = db.Read(func(m *map[string]string) { if *m == nil { *m = make(map[string]string) } val, ok := (*m)[key] if ok { existingUUID = val keyExists = true } }) if err != nil { return "", err } // 键存在则直接返回 if keyExists { return existingUUID, nil } // 键不存在则生成新UUID并写入 newUUID := uuid.NewString() err = db.Write(func(m *map[string]string) { if *m == nil { *m = make(map[string]string) } (*m)[key] = newUUID }) if err != nil { return "", err } return newUUID, nil } func main() { uuidVal, err := GetOrCreateUUID("MISSING-KEY") if err != nil { log.Fatal(err) } fmt.Println(uuidVal) }
方案2:使用嵌套结构体(需调整JSON格式)
如果你希望保留Data结构体,需要将JSON修改为包含identifiers字段的结构:
{ "identifiers": { "something": "35b7bd1e-0eab-11ef-8a72-ef7c0dade844", "something else": "35b7bdf0-0eab-11ef-8a73-67ce44126d91" } }
对应的代码实现:
package main import ( "fmt" "log" "os" "crawshaw.dev/jsonfile" "github.com/google/uuid" ) type Data struct { Identifiers map[string]string `json:"identifiers"` } func GetOrCreateUUID(key string) (string, error) { db, err := jsonfile.Load[Data]("resolver.json") if os.IsNotExist(err) { db, err = jsonfile.New[Data]("resolver.json") } if err != nil { return "", err } var existingUUID string keyExists := false err = db.Read(func(d *Data) { if d.Identifiers == nil { d.Identifiers = make(map[string]string) } val, ok := d.Identifiers[key] if ok { existingUUID = val keyExists = true } }) if err != nil { return "", err } if keyExists { return existingUUID, nil } newUUID := uuid.NewString() err = db.Write(func(d *Data) { if d.Identifiers == nil { d.Identifiers = make(map[string]string) } d.Identifiers[key] = newUUID }) if err != nil { return "", err } return newUUID, nil } func main() { uuidVal, err := GetOrCreateUUID("MISSING-KEY") if err != nil { log.Fatal(err) } fmt.Println(uuidVal) }
关键注意事项
- map初始化:无论是顶层map还是结构体中的map,首次创建文件时会为nil,必须先初始化才能进行键值操作。
- 原子性写入:
jsonfile.Write方法会原子性地将修改写入磁盘,避免文件损坏,适合你这种低写入量的场景。 - UUID依赖:代码中使用
github.com/google/uuid库生成UUID,需先执行go get github.com/google/uuid安装依赖。
内容的提问来源于stack exchange,提问作者George Livanoss
相关产品推荐
相关产品推荐

