gob解码结构中的接口与原始接口之间的区别

rol*_*lfl 5 go gob

当该类型嵌入到结构中时,我一直在努力理解编码/解码接口类型与完全没有嵌入时的区别.

使用以下示例:在操场上

注意代码声明了一个接口IFace.它声明了一个非导出的结构impl.它设置了一些采空区的方法Register,GobEncode以及GobDecodeimpl结构.

然后,它还声明了一个Data导出的结构,并且具有一个Foo接口类型的单个字段IFace.

所以,有一个接口,一个实现它的结构,以及一个容器结构,它有一个字段,其值是接口类型.

我的问题是容器结构Data很愉快地通过Gob gauntlet发送,当它通过时,它很高兴地对Data结构中的IFace字段进行编码和解码......太棒了!但是,我似乎无法通过gob gaunt只发送一个IFace值的实例.

我错过了什么神奇的召唤?

搜索错误消息会给出一些结果,但我相信我已经满足了Gob合同......而且"证明"就是成功的结构化.显然我错过了一些东西,却看不到它.

注意,程序的输出是:

Encoding {IFace:bilbo} now
Encoding IFace:baggins now
Decoded {IFace:bilbo} now
decode error: gob: local interface type *main.IFace can only be decoded from remote interface type; received concrete type impl
Decoded <nil> now
Run Code Online (Sandbox Code Playgroud)

实际代码是:

package main

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

type IFace interface {
    FooBar() string
}

type impl struct {
    value string
}

func init() {
    gob.Register(impl{})
}

func (i impl) FooBar() string {
    return i.value
}

func (i impl) String() string {
    return "IFace:" + i.value
}

func (i impl) GobEncode() ([]byte, error) {
    return []byte(i.value), nil
}

func (i *impl) GobDecode(dat []byte) error {
    val := string(dat)
    i.value = val
    return nil
}

func newIFace(val string) IFace {
    return impl{val}
}

type Data struct {
    Foo IFace
}

func main() {

    var network bytes.Buffer        // Stand-in for a network connection
    enc := gob.NewEncoder(&network) // Will write to network.
    dec := gob.NewDecoder(&network) // Will read from network.

    var err error

    var bilbo IFace
    bilbo = newIFace("bilbo")

    var baggins IFace
    baggins = newIFace("baggins")

    dat := Data{bilbo}

    fmt.Printf("Encoding %v now\n", dat)
    err = enc.Encode(dat)
    if err != nil {
        fmt.Println("encode error:", err)
    }

    fmt.Printf("Encoding %v now\n", baggins)
    err = enc.Encode(baggins)
    if err != nil {
        fmt.Println("encode error:", err)
    }

    var pdat Data
    err = dec.Decode(&pdat)
    if err != nil {
        fmt.Println("decode error:", err)
    }
    fmt.Printf("Decoded %v now\n", pdat)

    var pbag IFace
    err = dec.Decode(&pbag)
    if err != nil {
        fmt.Println("decode error:", err)
    }
    fmt.Printf("Decoded %v now\n", pbag)

}
Run Code Online (Sandbox Code Playgroud)

Cer*_*món 6

电话

err = enc.Encode(baggins)
Run Code Online (Sandbox Code Playgroud)

impl值传递给Encode. 它不传递类型的值IFace。文档http://research.swtch.com/interfaces可能有助于理解为什么会这样。该值被编码为具体类型impl

如果要解码为接口类型,则必须对接口类型进行编码。一种方法是传递一个指向接口值的指针:

err = enc.Encode(&baggins)
Run Code Online (Sandbox Code Playgroud)

在这个调用中,a*IFace被传递给 Encode。取消引用指针后,编码器看到该值是接口类型并将其编码为接口类型。因为 gob 包在转换值时会执行所有必要的解引用和间接,所以在调用 Encode 时额外的间接级别在解码时不需要额外的间接级别。

playground example