gpt4 book ai didi

types - Go 等效于类型继承(通过接口(interface)进行 gob 编码/解码)

转载 作者:IT王子 更新时间:2023-10-29 02:24:03 26 4
gpt4 key购买 nike

我正在尝试编写一个函数来编码/解码各种类型的消息。

在 OO 语言中,我会使用类型继承,但 Go 没有这个概念,引用:http://golang.org/doc/faq#inheritance ,因此,我在这里尝试使用“标记接口(interface)”样式来利用接口(interface)继承来达到此目的。

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

   line 1019// Common confusing case: local interface type, remote concrete type.

.. 是的,我觉得这很困惑!!

https://play.golang.org/p/ldEvQXIgEa 运行

我无法让它工作,我做错了什么?请帮忙!

更新:

(我也试过 gob.Register(m1) 但没有效果)。

我研究了类型嵌入,但它并没有做我想做的事情,正如你在这个例子中看到的(我已经从 jcbwlkr 的代码中修改):https//play .golang .org/p/P6AwVQqQcM(另请注意,我可能有数十种/数百种消息类型!)

很可能我找错了树,我需要放弃关于如何思考这个问题的整个想法(但这就是我目前正在尝试做的事情:学习如何“Think in Go” vs OO thinking)。使用类型嵌入是可行的,但我必须创建一个主类型,在其中嵌入(组合)所有可能的类型:gob 使解码成为可能,类型开关让我看到我得到了什么,但这一切 < em>感觉想想 非常可怕和不舒服。

(我习惯了静态和动态语言,所以我对鸭子打字很满意,但是这感觉就像一个折衷的房子,没有两端的舒适感!)。

所以我要问两件事:

  1. 如何解决这个特定问题(即理解什么是可能的与接口(interface)),和
  2. 设计备选方案(类型嵌入是其中之一,所以感谢您强调这一点):) .

这是损坏的代码:

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)
}

最佳答案

我不使用标记接口(interface),而是采用使用 Type Embedding 的方法并将编码/解码方法放在 Msg 类型上。

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)
}

View it on the Playground

您可以使用一些 New 方法来制作 ClientMsgServerMsg 结构,从而使这段代码更好。您还需要将返回值从 encode 传递到 bytes.NewBuffer 还是可以按原样使用它?

关于types - Go 等效于类型继承(通过接口(interface)进行 gob 编码/解码),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28568275/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com