寄存器类型后gob decode无法解码接口

Net*_*ave 7 methods interface go gob

我定义了这些类型:

func init() {
    gob.RegisterName("MyMessageHeader", MyMessageHeader{})
    gob.RegisterName("OtherMsg", OtherMsg{})
}

//
// Messages
//

type MyMessageHeader struct {
    MessageId InstanceIdType
    OtherId   uint64
}

type MyMessage interface {
    Id() *MyMessageHeader
}

type otherStruct struct {
    X uint8
    Y uint8
}
type OtherMsg struct {
    MyMessageHeader
    OtherField *otherStruct
}


func (m *OtherMsg) Id() *MyMessageHeader {
    return &m.MyMessageHeader
}

func MarshalMessage(m MyMessage) ([]byte, error) {
    var buff bytes.Buffer
    encoder := gob.NewEncoder(&buff)
    if err := encoder.Encode(&m); err != nil {
        return nil, errors.Newf("Could not marshal message: %v", err)
    }
    return buff.Bytes(), nil
}

func UnmarshalMessage(buf []byte) (MyMessage, error) {
    var msg MyMessage
    decoder := gob.NewDecoder(bytes.NewReader(buf))
    if err := decoder.Decode(&msg); err != nil {
        return nil, errors.Newf("Could not decode my message: %v", err)
    }
    return msg, nil
}
Run Code Online (Sandbox Code Playgroud)

当我尝试使用时UnmarshalMessage出现错误gob: OtherMsg is not assignable to type MyMessage。我与go 示例中用于编码和解码接口的用法没有区别。我究竟做错了什么?

icz*_*cza 6

错误消息说:

gob:OtherMsg 不可分配到类型 MyMessage

这是真的。MyMessage是一个接口,它需要实现器类型有一个方法:

Id() *MyMessageHeader
Run Code Online (Sandbox Code Playgroud)

一个 type 的值OtherMsg在它的方法 set中没有这样的方法,只有一个指向它的指针,即一个 type 的值*OtherMsg(因为OtherMsg.Id()有指针接收器)。

为了使它工作,注册一个类型的值*OtherMsg

gob.RegisterName("OtherMsg", &OtherMsg{})
Run Code Online (Sandbox Code Playgroud)

或者干脆:

gob.Register(&OtherMsg{})
Run Code Online (Sandbox Code Playgroud)

查看 Go Playground 上的一个工作示例:

func init() {
    gob.Register(&OtherMsg{})
}

func main() {
    var m MyMessage = &OtherMsg{
        MyMessageHeader: MyMessageHeader{
            MessageId: 1,
            OtherId:   2,
        },
        OtherField: "othervalue",
    }

    data, err := MarshalMessage(m)
    if err != nil {
        panic(err)
    }

    m2, err := UnmarshalMessage(data)
    if err != nil {
        panic(err)
    }
    fmt.Printf("%+v\n", m2)
}
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

&{MyMessageHeader:{MessageId:1 OtherId:2} OtherField:othervalue}
Run Code Online (Sandbox Code Playgroud)