Reputation: 587
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)
Upvotes: 2
Views: 4461
Reputation: 11164
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:
logDebug
flag to true, and rebuild the rpc
package, orServerCodec
that wraps the existing implementation and logs any errors returned by ReadRequestBody
/WriteResponse
. Upvotes: 6