Types Go等效于inheritace类型(通过接口进行gob编码/解码)

Types Go等效于inheritace类型(通过接口进行gob编码/解码),types,go,polymorphism,Types,Go,Polymorphism,我正在尝试编写一个函数,对各种类型的消息进行编码/解码 在OO语言中,我会使用类型继承,但Go没有这个概念,ref:,因此,这里我尝试使用标记接口样式来利用接口继承来实现这一目的 错误来自golang org src/encoding/gob/decode.go: line 1019// Common confusing case: local interface type, remote concrete type. 。。是的,我觉得这很困惑 运行这个 我不能让它工作,我做错了什么?救

我正在尝试编写一个函数,对各种类型的消息进行编码/解码

在OO语言中,我会使用类型继承,但Go没有这个概念,ref:,因此,这里我尝试使用标记接口样式来利用接口继承来实现这一目的

错误来自golang org src/encoding/gob/decode.go:

   line 1019// Common confusing case: local interface type, remote concrete type.
。。是的,我觉得这很困惑

运行这个

我不能让它工作,我做错了什么?救命啊

更新:

我还尝试gob.Registerm1,但没有效果

我已经研究了类型嵌入,但它没有做我试图做的事情,正如您在这个例子中看到的,我已经从jcbwlkr的代码中修改过:https//play.golang.org/p/P6AwVQqQcM也要知道我可能有几十种/数百种消息类型

很可能是我找错了方向,我需要抛开我如何思考这个问题的整个想法,但这就是我目前正在努力做的:学习如何在Go和OO思维中思考。使用类型嵌入是可行的,但我必须创建一个主类型,该主类型嵌入了其中所有可能的类型:gob使解码成为可能,类型开关让我看到我得到了什么,但这一切都让我感到非常害怕和不安

我已经习惯了静态和动态语言,所以我对duck类型很满意,但这感觉就像一个中途之家,没有任何一方的舒适

我在这里要问两件事:

如何解决这个特殊问题(了解可能发生的情况) 具有接口,以及 设计方案和类型嵌入是必要的 其中之一,因此感谢您突出显示:。 在这里;这是坏代码:

package main

import (
    "fmt"
    "bytes"
    "log"
    "encoding/gob"
)

type Msger interface {
    IsMsg()
}

type ClientMsg struct {
    Id      string
}
type ServerMsg struct {
    Id      string
}

func (m ClientMsg) IsMsg() { }
func (m ServerMsg) IsMsg() { }

func encode(m Msger) (bb bytes.Buffer) {
    enc := gob.NewEncoder(&bb)
    err := enc.Encode(m)
    if err != nil {
        log.Fatal("Cannot encode! err=", err)
    }
    return
}

func decode(m Msger, bb bytes.Buffer) {     // for A
//func decode(m *Msger, bb bytes.Buffer) {  // for B, C
    dec := gob.NewDecoder(&bb)
    err := dec.Decode(&m)
    if err != nil {
        log.Fatal("Cannot decode Msg! err=", err)
    }
    return
}

func main() {
    m1 := ClientMsg{"id_1"}
    b1 := encode(m1)
    p_bb := bytes.NewBuffer(b1.Bytes())

    var mDecoded ClientMsg // for A, B, C
    //var mDecoded interface{} // D: : cannot use mDecoded (type interface {}) as type Msger in argument to decode: interface {} does not implement Msger (missing IsMsg method)
    decode(mDecoded, *p_bb)     // A: gives: Cannot decode Msg! err=gob: local interface type *main.Msger can only be decoded from remote interface type; received concrete type ClientMsg = struct { Id string; }

    //decode(mDecoded, *p_bb)  // B: gives: cannot use mDecoded (type ClientMsg) as type *Msger in argument to decode: *Msger is pointer to interface, not interface
    //decode(&mDecoded, *p_bb) // C: gives: cannot use &mDecoded (type *ClientMsg) as type *Msger in argument to decode: *Msger is pointer to interface, not interface

    fmt.Printf("m1 Decoded='%v'\n", mDecoded)
}

与使用标记接口不同,我将采用一种使用的方法,并将encode/decode方法放在Msg类型上


您可以使用一些新的方法来创建ClientMsg或ServerMsg结构,从而使代码更漂亮。您是否还需要将encode返回值传递给bytes.NewBuffer,或者您可以按原样使用它?

发现编码接口需要对指针进行编码,但仍然无法正确解码!ref Hi jcbwlkr-感谢您的反馈,我已经研究了类型嵌入,但它并没有完成我试图做的事情,正如您在这个示例中看到的,我从您的代码中修改了:@SigridHaughty我明白您的意思。我觉得这里有一个解决方案,但我还没有看到。祝你好运!
package main

import (
    "bytes"
    "encoding/gob"
    "fmt"
    "log"
)

type Msg struct {
    Id string
}

type ClientMsg struct {
    Msg
}
type ServerMsg struct {
    Msg
}

func (m *Msg) encode() (bb bytes.Buffer) {
    enc := gob.NewEncoder(&bb)
    err := enc.Encode(m)
    if err != nil {
        log.Fatal("Cannot encode! err=", err)
    }
    return
}

func (m *Msg) decode(bb *bytes.Buffer) {
    dec := gob.NewDecoder(bb)
    err := dec.Decode(m)
    if err != nil {
        log.Fatal("Cannot decode Msg! err=", err)
    }
    return
}

func main() {
    // Make a message and encode it to a bytes.Buffer
    m1 := &ClientMsg{Msg{"id_1"}}
    b1 := m1.encode()
    p_bb := bytes.NewBuffer(b1.Bytes())

    // Make a new message and decode the bytes.Buffer from the first
    m2 := &ClientMsg{Msg{}}
    m2.decode(p_bb)

    fmt.Printf("m2 Decoded = '%v'\n", m2.Msg.Id)
}