当结构具有嵌套结构时,golang rpc 不返回

标签 go rpc

更新

从 gob 编码转变为 json 解决了这个问题。但是我仍然想知道为什么这对 gob 不起作用。

所以我的客户端代码是这样的

account := new(database.Account)

err := client.Call("AccountDb.FindAccount", "username", account)

if err != nil {
    logger.FATAL.Print(err.Error())
    return
}

logger.INFO.Print(account)

在服务器端 AccountDb.FindAccount 看起来像这样

func (t *AccountDb) FindAccount(args *string, reply *Account) error {

    reply.Username = "this is a test"

    return nil
}

Account 的结构如下所示

type Account struct {
    Id           int
    Username     string
    Password     string
    Email        string
    Created      time.Time
    LastLoggedIn time.Time
    AccessLevel  int

    Banned struct {
        reason  string
        expires time.Time
    }
}

如果我尝试执行 rpc,请求将启动并且服务器将执行该过程。然而,程序然后挂起并且程序不返回!但是,如果我从 Account 结构中删除 Banned 匿名结构,它就可以正常工作!为什么是这样?这个问题有解决办法吗?

编辑 客户端和服务器注册代码如下所示

客户端

client, err = rpc.DialHTTP("tcp", "127.0.0.1:9001")

if err != nil {
    logger.FATAL.Panic(err.Error())
}

服务器

defer db.Close()

account := new(database.AccountDb)
account.Database = db

rpc.Register(account)
rpc.HandleHTTP()
l, e := net.Listen("tcp", ":9001")

if e != nil {
    logger.FATAL.Fatal("listen error:", e)
}
http.Serve(l, nil)

最佳答案

显然,gob 编码器无法编码 RPC 响应,因为 Banned 结构没有导出字段。这playground example显示错误:

encode error: gob: type struct { reason string; expires time.Time } 
has no exported fields

如果您通过大写导出 reason/expires 字段,则 gob 往返工作正常(参见 http://play.golang.org/p/YrYFsk6trQ)。

JSON 编码器还要求导出序列化字段,但如果结构没有序列化字段,它不会返回错误。解码仅返回默认值/零值。运行 http://play.golang.org/p/OBBkB4tPcZ并注意 Banned 信息在往返过程中丢失了。

如果需要检测rpc包中的此类错误,有两种选择:

  1. 编辑 rpc/debug.go ,将logDebug标志设置为true,并重建rpc包,或者
  2. 实现一个ServerCodec,包装现有实现并记录ReadRequestBody/WriteResponse 返回的任何错误。

关于当结构具有嵌套结构时,golang rpc 不返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24145058/

相关文章:

c# - Thrift 中缺少 "objects"是不是很尴尬?

go - `(*RawMessage)(nil)` 是什么意思?

Go 经常解析失败(goquery)

go - 在 VM 中运行 go-bindata 会导致输入/输出错误?

c# - JayRock 间歇性缺失值

c# - C#和android应用程序之间的RPC通信

linux - 使用带有 Go 和 GoCV 的 OpenVINO 加载预训练的 DNN 模型 - 符号查找错误

mongodb - 如何使用 golang 和官方 mongo 驱动程序检查记录是否存在

java - JSON RPC Java dzhuvinov - 如何设置用户名和密码?