You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)
}

关键注意事项

  1. map初始化:无论是顶层map还是结构体中的map,首次创建文件时会为nil,必须先初始化才能进行键值操作。
  2. 原子性写入:jsonfile.Write方法会原子性地将修改写入磁盘,避免文件损坏,适合你这种低写入量的场景。
  3. UUID依赖:代码中使用github.com/google/uuid库生成UUID,需先执行go get github.com/google/uuid安装依赖。

内容的提问来源于stack exchange,提问作者George Livanoss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 04:50:14