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]
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)