使用gob无法正确地将数据存储到文件中

4
当我尝试使用gob编码器将类型为map[mapKey]string的地图保存到文件中时,它没有将字符串保存在文件中。
这里的mapKey是结构体,地图值是长json字符串。
type mapKey struct{
    Id1 string
    Id2 string
}

每当我使用嵌套的map而不是struct时:

var m = make(map[string]map[string]string)

它正常工作并正确保存字符串。我不确定我在这里遗漏了什么。

编码、解码并将其保存到文件的代码:

func Save(path string, object interface{}) error {
    file, err := os.Create(path)
    if err == nil {
        encoder := gob.NewEncoder(file)
        encoder.Encode(object)
    }
    file.Close()
    return err
}

// Decode Gob file
func Load(path string, object interface{}) error {
    file, err := os.Open(path)
    if err == nil {
        decoder := gob.NewDecoder(file)
        err = decoder.Decode(object)
    }
    file.Close()
    return err
}

func Check(e error) {
    if e != nil {
        _, file, line, _ := runtime.Caller(1)
        fmt.Println(line, "\t", file, "\n", e)
        os.Exit(1)
    }
}

1
为什么你不使用嵌套映射呢?可能需要将输入作为嵌套映射。 - Endre Simo
根据 https://blog.golang.org/go-maps-in-action 博客,如果您有一个嵌套的映射类型结构进行映射,则建议使用 Struct。 然而,我是 Go 的新手,不确定是否可以使用 struct。 它没有给出任何编译错误,但它没有保存长字符串。 - rohan
1个回答

5

编码 map[mapKey]string 类型的值没有什么特殊的。

参见此非常简单的工作示例,使用指定的读写器:

func save(w io.Writer, i interface{}) error {
    return gob.NewEncoder(w).Encode(i)

}
func load(r io.Reader, i interface{}) error {
    return gob.NewDecoder(r).Decode(i)
}

使用内存缓冲区 (bytes.Buffer) 进行测试:

m := map[mapKey]string{
    {"1", "2"}: "12",
    {"3", "4"}: "34",
}
fmt.Println(m)

buf := &bytes.Buffer{}
if err := save(buf, m); err != nil {
    panic(err)
}

var m2 map[mapKey]string
if err := load(buf, &m2); err != nil {
    panic(err)
}
fmt.Println(m2)

按照预期输出(在Go Playground上尝试):

map[{1 2}:12 {3 4}:34]
map[{1 2}:12 {3 4}:34]

你已经有了一份可用的代码,但是需要使用指针值调用Load()(否则Decoder.Decode()无法修改其值)。
另外还有几点需要改进:
  • 在你的示例中,你没有处理Encoder.Encode()返回的错误(检查一下就会发现问题;常见的问题是在结构体mapKey中使用没有公开字段的结构体,在这种情况下会返回一个错误gob: type main.mapKey has no exported fields)。
  • 此外,你应该将File.Close()作为延迟函数调用。
  • 如果打开文件失败,你应该及早返回并且不应该关闭文件。
这是你的代码的修正版本:
func Save(path string, object interface{}) error {
    file, err := os.Create(path)
    if err != nil {
        return err
    }
    defer file.Close()
    return gob.NewEncoder(file).Encode(object)
}

func Load(path string, object interface{}) error {
    file, err := os.Open(path)
    if err != nil {
        return err
    }
    defer file.Close()
    return gob.NewDecoder(file).Decode(object)
}

测试它:

m := map[mapKey]string{
    {"1", "2"}: "12",
    {"3", "4"}: "34",
}
fmt.Println(m)

if err := Save("testfile", m); err != nil {
    panic(err)
}

var m2 map[mapKey]string
if err := Load("testfile", &m2); err != nil {
    panic(err)
}
fmt.Println(m2)

如预期输出:

map[{1 2}:12 {3 4}:34]
map[{1 2}:12 {3 4}:34]

本来想建议您检查是否像icza在这里描述的那样使用了指针——除了其他非常好的建议。 - TehSphinX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接