Go:方法调用后对象不持久

时间:2014-05-04 17:29:37

标签: methods go arguments

我正在尝试为我正在编写的程序实现MarshalBinary和UnmarshalBinary,但是在调用UnmarshalBinary之后我的更改似乎没有持续。

我的MWE:

package main

import (
    "encoding/binary"
    "fmt"
    "strconv"
)

type test struct {
    var1 uint32
    var2 uint32
}

func (self test) MarshalBinary() ([]byte, error) {
    tmp := make([]byte, 8)
    binary.BigEndian.PutUint32(tmp[0:4], self.var1)
    binary.BigEndian.PutUint32(tmp[4:8], self.var2)
    return tmp, nil
}

func (self test) UnmarshalBinary(data []byte) error {
    self.var1 = binary.BigEndian.Uint32(data[0:4])
    self.var2 = binary.BigEndian.Uint32(data[4:8])
    fmt.Printf("UMB\t%s\n", self.String())
    return nil
}

func (self test) String() string {
    return "test struct\tvar1 = 0x" +
        strconv.FormatUint(uint64(self.var1), 16) +
        "\tvar2 = " + strconv.FormatUint(uint64(self.var2), 16)
}

func main() {
    in := test{
        var1: uint32(0x39471208),
        var2: uint32(0x45387182),
    }
    fmt.Printf("In\t%s\n", in.String())
    bin, _ := in.MarshalBinary()
    fmt.Printf("Bin\t0x%x\n", bin)
    var out test
    out.UnmarshalBinary(bin)
    fmt.Printf("Out\t%s\n", out.String())
}

我的输出:

In  test struct var1 = 0x39471208   var2 = 45387182
Bin 0x3947120845387182
UMB test struct var1 = 0x39471208   var2 = 45387182
Out test struct var1 = 0x0  var2 = 0

1 个答案:

答案 0 :(得分:2)

self参数不是引用类型,因此当您调用方法test.UnmarshalBinary()时,它会按值复制,整个结构被复制到堆栈中,并在UnmarshalBinary()返回时释放。从 A Tour of Go 的幻灯片54开始:

  

使用指针接收器有两个原因。首先,要避免   复制每个方法调用的值(如果值更有效   type是一个大型结构)。 ...

(我很难找到一个官方消息来源说收件人是通过价值传递的;有人知道更权威的吗?)

尝试更改接收器以接受指针接收器:

func (self *test) MarshalBinary() ([]byte, error) {
    tmp := make([]byte, 8)
    binary.BigEndian.PutUint32(tmp[0:4], self.var1)
    binary.BigEndian.PutUint32(tmp[4:8], self.var2)
    return tmp, nil
}

func (self *test) UnmarshalBinary(data []byte) error {
    self.var1 = binary.BigEndian.Uint32(data[0:4])
    self.var2 = binary.BigEndian.Uint32(data[4:8])
    fmt.Printf("UMB\t%s\n", self.String())
    return nil
}

func (self *test) String() string {
    return "test struct\tvar1 = 0x" +
        strconv.FormatUint(uint64(self.var1), 16) +
        "\tvar2 = " + strconv.FormatUint(uint64(self.var2), 16)
}

你会看到更好的输出:

In  test struct var1 = 0x39471208   var2 = 45387182
Bin 0x3947120845387182
UMB test struct var1 = 0x39471208   var2 = 45387182
Out test struct var1 = 0x39471208   var2 = 45387182