我有一些代码被抛出了,实际上我很困惑--我以前使用过RPC和JSON方面的东西,但当RPC在本地正常工作时,我似乎无法让它在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)
}
defer conn.Close()
c := jsonrpc.NewClient(conn)
err = c.Call("FooManager.GetAvailableFoos", foos, &foos)
if err != nil {
log.Println(foos)
log.Fatal("GetAvailableFoos error:", err)
}
log.Println("Success: ", foos)
}(这里也没有tcp可用的urgh!http://play.golang.org/p/HmK-K09D2J )
输出非常令人惊讶,因为它表明编组出现了问题,而不是实际的数据--在wireshark中运行它,我可以看到数据以正确的形式发送(我在另一个问题中成功地使用了类似的技术),但我无法让它停止抛出编组错误。
运行它的输出如下:
2015/09/07 10:04:35 Added type *main.fakeFoo
2015/09/07 10:04:35 Using standard function call
2015/09/07 10:04:35 availableFoos: []main.Foo
2015/09/07 10:04:35 *out is []main.Foo
2015/09/07 10:04:35 Out is: []main.Foo
2015/09/07 10:04:35 [0x1870a540]
2015/09/07 10:04:35 Using RPC call
2015/09/07 10:04:35 Incoming!
2015/09/07 10:04:35 [0x1870a540]
2015/09/07 10:04:35 GetAvailableFoos error:json: cannot unmarshal object into Go value of type main.Foo
exit status 1我是缺少了接口/输入技巧,还是这是Go编组中的一个bug?
发布于 2015-09-07 02:48:17
所有封送/解封送处理都存在此问题。
您可以从接口类型变量封送,因为对象是本地存在的,因此反射器知道底层类型。
不能将其解封为接口类型,因为反射器不知道要将哪种具体类型提供给新实例以接收封送数据。
在一些封送/解组框架中,我们需要更多的信息来帮助反射器。例如,在Java (杰克逊)中,我们使用JsonTypeInfo注释来指定类类型,引用这。
对于golang,您可以自己为自己的类型实现解编组器接口。请参阅我如何解封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)
}https://stackoverflow.com/questions/32428797
复制相似问题