解组到接口类型

我有一些代码被丢弃了,实际上我很难过 - 我以前使用过 RPC 和 JSON 方面的东西,但是当它在本地工作正常时,我似乎无法让它在 RPC 上工作。


package main


import (

    "log"

    "net"

    "net/rpc"

    "net/rpc/jsonrpc"

    "reflect"

)


type Foo interface {

    SayHello() error

}


type fakeFoo struct {

    internalValue string

}


func NewFakeFoo() *fakeFoo {

    f := &fakeFoo{}

    f.internalValue = "123456789012347"

    return f

}


func (m *fakeFoo) SayHello() error {

    return nil

}


type FooManager struct {

    availableFoos []Foo

}


func NewFooManager() *FooManager {

    p := new(FooManager)

    p.availableFoos = make([]Foo, 0)

    return p

}


func AddFoo(mm *FooManager, m Foo) {

    mm.availableFoos = append(mm.availableFoos, m)

    log.Println("Added type ", reflect.TypeOf(m))

}


func (mm *FooManager) GetAvailableFoos(in []Foo, out *[]Foo) error {


    log.Println("availableFoos:", reflect.TypeOf(mm.availableFoos))

    log.Println("*out is", reflect.TypeOf(*out))


    *out = append(in, mm.availableFoos...)


    log.Println("Out is:", reflect.TypeOf(*out))


    return nil

}


func startServer(mm *FooManager) {

    server := rpc.NewServer()

    server.Register(mm)


    l, e := net.Listen("tcp", ":8222")

    if e != nil {

        log.Fatal("listen error:", e)

    }


    for {

        conn, err := l.Accept()

        log.Println("Incoming!")

        if err != nil {

            log.Fatal(err)

        }


        go server.ServeCodec(jsonrpc.NewServerCodec(conn))

    }

}


func main() {

    fake1 := NewFakeFoo()


    fooHolder := NewFooManager()

    AddFoo(fooHolder, fake1)

    go startServer(fooHolder)


    log.Println("Using standard function call")

    var foos []Foo

    fooHolder.GetAvailableFoos(foos, &foos)

    log.Println(foos)


    log.Println("Using RPC call")

    conn, err := net.Dial("tcp", "localhost:8222")

    if err != nil {

        log.Fatalln(err)

    }

(也在这里,但没有可用的 tcp urgh!http: //play.golang.org/p/HmK-K09D2J )


输出非常令人惊讶,因为它表明编组出了问题而不是实际数据 - 在wireshark中运行它我可以看到以正确的形式发送的数据(我在另一个问题中使用类似的技术取得了成功)但是可以不是为了我的生活得到这个停止抛出编组错误。

我是否缺少接口/类型技巧,或者这是 Go 编组中的错误?


幕布斯6054654
浏览 158回答 1
1回答

繁花如伊

所有编组/解组都有这个问题。您可以从接口类型变量进行编组,因为对象存在于本地,因此反射器知道底层类型。您不能解组到接口类型,因为反射器不知道将哪种具体类型提供给新实例以接收编组数据。在一些编组/解组框架中,我们需要额外的信息来帮助反射器。比如在Java Json( jackson )中,我们使用JsonTypeInfo注解来指定类的类型,参考这个。对于 golang,你可以自己为自己的类型实现Unmarshaler接口。请参阅如何解组 JSON?// RawString is a raw encoded JSON object.// It implements Marshaler and Unmarshaler and can// be used to delay JSON decoding or precompute a JSON encoding.type RawString string// MarshalJSON returns *m as the JSON encoding of m.func (m *RawString) MarshalJSON() ([]byte, error) {    return []byte(*m), nil}// UnmarshalJSON sets *m to a copy of data.func (m *RawString) UnmarshalJSON(data []byte) error {    if m == nil {        return errors.New("RawString: UnmarshalJSON on nil pointer")    }    *m += RawString(data)    return nil}const data = `{"i":3, "S":{"phone": {"sales": "2223334444"}}}`type A struct {    I int64    S RawString `sql:"type:json"`}func main() {    a := A{}    err := json.Unmarshal([]byte(data), &a)    if err != nil {        log.Fatal("Unmarshal failed", err)    }    fmt.Println("Done", a)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go