【问题标题】:Not able to store data in file properly using gob无法使用 gob 将数据正确存储在文件中
【发布时间】:2016-11-07 08:26:50
【问题描述】:

当我尝试使用gob 编码器将map[mapKey]string 类型的地图保存到文件中时,它不会将字符串保存在文件中。

这里mapKey是struct,map值是长json字符串。

type mapKey struct{
    Id1 string
    Id2 string
}

每当我使用嵌套映射而不是结构时:

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

【问题讨论】:

  • 以及为什么不使用嵌套地图。可能要求输入是嵌套地图。
  • @SimoEndre :根据blog.golang.org/go-maps-in-action 博客,如果您有用于映射的嵌套映射类型结构,他们建议使用 Struct。但是我是 Go 新手,我不确定是否可以使用该结构。它没有给出任何编译错误,但它没有保存长字符串。

标签: file dictionary go gob


【解决方案1】:

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() 返回的error(检查一下,您会发现问题所在;一个常见问题是使用没有导出字段的结构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 指针 -- 以及其他非常好的建议。
猜你喜欢
  • 2019-04-14
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 2021-09-19
  • 2019-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多