duanjiao6711
duanjiao6711
2014-06-10 15:32

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

已采纳

UPDATE

moving from gob encoding to json fixed the issue. However I would still like to know why this was failing to work with gob.

so my client code looks like this

account := new(database.Account)

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

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

logger.INFO.Print(account)

On the server side AccountDb.FindAccount looks like this

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

    reply.Username = "this is a test"

    return nil
}

The struct for Account looks like this

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
    }
}

if I attempt to perform the rpc the requests starts and the server executes the procedure. However the program then hangs and the procedure does not return! If however I remove the Banned anonymous struct from the Account struct it works fine! Why is this? is there a solution to this problem?

edit the client and server register code looks like this

Client

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

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

Server

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条回答

  • dr5648 dr5648 7年前

    Evidently, the gob encoder fails to marshal the RPC response because the Banned struct has no exported fields. This playground example exhibits the error:

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

    If you export the reason/expires fields by capitalizing them, the gob round-trip works OK (see http://play.golang.org/p/YrYFsk6trQ).

    The JSON encoder also requires that serialized fields are exported, but it does not return an error if a struct has none. The decode just returns default/zero values. Run http://play.golang.org/p/OBBkB4tPcZ and note that the Banned information is lost on the round-trip.

    If you need to detect these kinds of errors in the rpc package, there are two options:

    1. Edit rpc/debug.go, set the logDebug flag to true, and rebuild the rpc package, or
    2. Implement a ServerCodec that wraps the existing implementation and logs any errors returned by ReadRequestBody/WriteResponse.
    点赞 评论 复制链接分享

相关推荐