存储Go编码数据的通用函数

huangapple go评论72阅读模式
英文:

Generic function to store Go Encoded Data

问题

我需要编写一个通用函数,可以将对象存储为gobjects。

func hash_store(data interface{}) {
  // 初始化一个 *bytes.Buffer
  m := new(bytes.Buffer) 
  // *bytes.Buffer 满足 io.Writer 接口,可以在 gob.NewEncoder() 中使用
  enc := gob.NewEncoder(m)
  // gob.Encoder 有一个 Encode 方法,接受数据项作为参数
  enc.Encode(data)
  // bytes.Buffer 类型有一个 Bytes() 方法,返回类型为 []byte,可以作为 ioutil.WriteFile() 的参数
  err := ioutil.WriteFile("dep_data", m.Bytes(), 0600) 
  if err != nil {
    panic(err)
  }
  fmt.Printf("刚刚保存了所有的 depinfo:%v\n", data)

  n, err := ioutil.ReadFile("dep_data")
  if err != nil {
    fmt.Printf("无法读取文件")
    panic(err)
  } 
  // 使用 n,类型为 []byte,创建一个 bytes.Buffer 类型
  p := bytes.NewBuffer(n) 
  // bytes.Buffer 满足 io.Writer 接口,可以在 gob.NewDecoder() 中使用
  dec := gob.NewDecoder(p)
  // 创建一个我们将用解码的 gob 填充的 map 引用类型
  e := make(map[string]string)
  // 我们必须解码到一个指针中,所以我们将 e 的地址传递进去
  err = dec.Decode(&e)
  if err != nil {
    fmt.Printf("无法解码")
    panic(err)
  }

  fmt.Println("读取 dep_data 后打印:", e)
}

在这个函数中,我知道要存储在 map[string]string 中的数据类型。但是我需要编写一个通用函数,在不知道数据类型的情况下将其存储为 gobject 文件。

英文:

I need to write a generic function which can store objects as gobjects.

func hash_store(data map[string]string) {
  //initialize a *bytes.Buffer
  m := new(bytes.Buffer) 
  //the *bytes.Buffer satisfies the io.Writer interface and can
  //be used in gob.NewEncoder() 
  enc := gob.NewEncoder(m)
  //gob.Encoder has method Encode that accepts data items as parameter
  enc.Encode(data)
  //the bytes.Buffer type has method Bytes() that returns type []byte, 
  //and can be used as a parameter in ioutil.WriteFile() 
  err := ioutil.WriteFile("dep_data", m.Bytes(), 0600) 
  if err != nil {
          panic(err)
  }
  fmt.Printf("just saved all depinfo with %v\n", data)

  n,err := ioutil.ReadFile("dep_data")
        if err != nil {
                fmt.Printf("cannot read file")
                panic(err)
        } 
        //create a bytes.Buffer type with n, type []byte
        p := bytes.NewBuffer(n) 
        //bytes.Buffer satisfies the interface for io.Writer and can be used
        //in gob.NewDecoder() 
        dec := gob.NewDecoder(p)
        //make a map reference type that we'll populate with the decoded gob 
        //e := make(map[int]string)
         e := make(map[string]string)
        //we must decode into a pointer, so we'll take the address of e 
        err = dec.Decode(&e)
        if err != nil {
                fmt.Printf("cannot decode")
                panic(err)
        }

        fmt.Println("after reading dep_data printing ",e)
}

In this function I know the data type to be stored in map[string]string . But I need to write a generic function where I don't know data type and still store it as a gobject in a file.

答案1

得分: 4

将你的具体类型(map[string]string)更改为空接口类型(interface{})。
参见这个相关问题,了解为什么这样做。

编码:

func store(data interface{}) {
  m := new(bytes.Buffer) 
  enc := gob.NewEncoder(m)

  err := enc.Encode(data)
  if err != nil { panic(err) }

  err = ioutil.WriteFile("dep_data", m.Bytes(), 0600) 
  if err != nil { panic(err) }
}

解码:

func load(e interface{}) {
	n,err := ioutil.ReadFile("dep_data")
	if err != nil { panic(err) } 

	p := bytes.NewBuffer(n) 
	dec := gob.NewDecoder(p)

	err = dec.Decode(e)
	if err != nil { panic(err) }
}

你在load中放入的值必须是使用gob存储在文件中的类型的指针。

map[string]string的示例:

org := map[string]string{"foo": "bar"}
store(org)

var loadedMap map[string]string
load(&loadedMap)

fmt.Println(loadedMap["foo"]) // bar
英文:

Change your concrete type (map[string]string) to the empty interface type (interface{}).
See this related question why this works.

Encoding:

func store(data interface{}) {
  m := new(bytes.Buffer) 
  enc := gob.NewEncoder(m)

  err := enc.Encode(data)
  if err != nil { panic(err) }

  err = ioutil.WriteFile("dep_data", m.Bytes(), 0600) 
  if err != nil { panic(err) }
}

Decoding:

func load(e interface{}) {
	n,err := ioutil.ReadFile("dep_data")
	if err != nil { panic(err) } 

	p := bytes.NewBuffer(n) 
	dec := gob.NewDecoder(p)

	err = dec.Decode(e)
	if err != nil { panic(err) }
}

The value you put in load must be a pointer of the type you stored in the file using gob.

Example for map[string]string:

org := map[string]string{"foo": "bar"}
store(org)

var loadedMap map[string]string
load(&loadedMap)

fmt.Println(loadedMap["foo"]) // bar

答案2

得分: 0

当你对数据进行编码时,给编码器一个 *interface{},然后你可以使用 *interface{} 进行解码。

var to_enc interface{} = ...;
god.NewEncoder(...).Encode(&to_enc);
...
var to_dec interface{}
god.NewDecoder(...).Decode(&to_dec);
英文:

When you encode the data, give the Encoder a *interface{}, then you can decoded with a *interface{}

var to_enc interface{} = ...;
god.NewEncoder(...).Encode(&to_enc);
...
var to_dec interface{}
god.NewDecoder(...).Decode(&to_dec);

huangapple
  • 本文由 发表于 2013年12月2日 07:11:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/20318445.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定