douyi4544 2016-07-05 13:16
浏览 32
已采纳

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

When I try to save the map of type map[mapKey]string into a file using gob encoder, it is not saving string in file.

Here mapKey is struct and map value is long json string.

type mapKey struct{
    Id1 string
    Id2 string
}

And whenever I am use nested map instead of the struct like:

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

It is working fine and saving string properly. I am not sure what I am missing here.

Code to encode, decode and save it in file:

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, "
", e)
        os.Exit(1)
    }
}
  • 写回答

1条回答 默认 最新

  • duanlu1959 2016-07-05 13:56
    关注

    There is nothing special in encoding a value of type map[mapKey]string.

    See this very simple working example which uses the specified reader/writer:

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

    Testing it with an in-memory buffer (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)
    

    Output as expected (try it on the Go Playground):

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

    You have a working code, but know that you have to call Load() with a pointer value (else Decoder.Decode() wouldn't be able to modify its value).

    Also a few things to improve it:

    • In your example you are swallowing the error returned by Encoder.Encode() (check it and you'll see what the problem is; a common problem is using a struct mapKey with no exported fields in which case an error of gob: type main.mapKey has no exported fields would be returned).
    • Also you should call File.Close() as a deferred function.
    • Also if opening the file fails, you should return early and you shouldn't close the file.

    This is the corrected version of your code:

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

    Testing it:

    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)
    

    Output as expected:

    map[{1 2}:12 {3 4}:34]
    map[{1 2}:12 {3 4}:34]
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥35 平滑拟合曲线该如何生成
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 自己瞎改改,结果现在又运行不了了
  • ¥15 链式存储应该如何解决
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站