更新
从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)
答案 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
包中检测到这类错误,有两种选择:
logDebug
标记设置为true,然后重建rpc
包,或ServerCodec
并记录ReadRequestBody
/ WriteResponse
返回的所有错误。