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

时间:2014-06-10 15:32:46

标签: 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结构中删除禁止的匿名结构,它工作正常!为什么是这样?有这个问题的解决方案吗?

编辑 客户端和服务器注册码看起来像这样

客户端

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)

1 个答案:

答案 0 :(得分:6)

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

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

如果您通过大写它们来导出原因/过期字段,那么gob往返工作正常(请参阅http://play.golang.org/p/YrYFsk6trQ)。

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

如果您需要在rpc包中检测到这类错误,有两种选择:

  1. 修改rpc/debug.go,将logDebug标记设置为true,然后重建rpc包,或
  2. 实施包装现有实施的ServerCodec并记录ReadRequestBody / WriteResponse返回的所有错误。