
Gorilla Toolkit 的 jsonrpc 包要求响应结构体的所有字段必须是导出(首字母大写)的公共字段,否则 JSON 编码器无法序列化,导致 "result": {} 的空对象响应。
gorilla toolkit 的 `jsonrpc` 包要求响应结构体的所有字段必须是导出(首字母大写)的公共字段,否则 json 编码器无法序列化,导致 "result": {} 的空对象响应。
在使用 Gorilla Toolkit 的 github.com/gorilla/rpc/v2/json2(或旧版 v1/json)实现 JSON-RPC 服务时,一个常见却容易被忽略的问题是:方法执行成功、无错误返回,但客户端收到的 result 却始终为空对象 {}。根本原因在于 Go 的 JSON 序列化机制——encoding/json 包只能编码导出(exported)字段,即字段名必须以大写字母开头。
回顾你的代码:
type Response struct {
sum int // ❌ 非导出字段:小写开头 → JSON 编码时被忽略
message string // ❌ 同上
}尽管你在 Add 方法中正确赋值了 reply.sum 和 reply.message,但由于这两个字段未导出,json.Marshal()(由 Gorilla RPC 内部调用)在序列化 *Response 时会跳过它们,最终生成空 JSON 对象 {},对应 "result": {}。
✅ 正确写法是将字段改为导出形式,并推荐使用符合 Go 命名惯例的驼峰式命名:
type Response struct {
Sum int `json:"sum"` // ✅ 导出字段;可选:显式指定 JSON 键名
Message string `json:"message"` // ✅ 同上
}同时,更新你的 RPC 方法签名(注意:Gorilla RPC 要求 reply 参数为指针类型,且需可被 JSON 编码):
func (t *Arith) Add(r *http.Request, args *Args, reply *Response) error {
reply.Sum = args.A + args.B
reply.Message = "Do math"
return nil
}完整可运行示例片段(精简版):
package main
import (
"log"
"net/http"
"github.com/gorilla/rpc/v2"
"github.com/gorilla/rpc/v2/json2"
)
type Args struct {
A, B int `json:"A,B"`
}
type Response struct {
Sum int `json:"sum"`
Message string `json:"message"`
}
type Arith int
func (t *Arith) Add(r *http.Request, args *Args, reply *Response) error {
reply.Sum = args.A + args.B
reply.Message = "Do math"
return nil
}
func main() {
s := rpc.NewServer()
s.RegisterCodec(json2.NewCodec(), "application/json")
s.RegisterService(new(Arith), "Arith")
http.Handle("/rpc", s)
log.Println("RPC server listening on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}发起请求(如用 curl):
curl -X POST http://localhost:8080/rpc \
-H "Content-Type: application/json" \
-d '{"method":"Arith.Add","params":[{"A":10,"B":2}],"id":1}'预期响应:
{
"result": {"sum": 12, "message": "Do math"},
"error": null,
"id": 1
}⚠️ 注意事项:
- 不要依赖匿名结构体或私有字段传递响应数据;
- 若需兼容不同 JSON 键名(如前端期望 total 而非 Sum),务必通过 json tag 显式声明:Sum intjson:"total``;
- 所有嵌套结构体中的字段也必须导出,否则深层字段同样丢失;
- Gorilla RPC 不支持返回值方式(如 func(...) (Response, error)),必须使用 reply *T 指针参数;
- 使用 *string 能工作,是因为 string 是基本类型,其值本身可直接编码;而结构体需逐字段反射,故受导出规则严格约束。
总结:Gorilla JSON-RPC 的响应空对象问题,99% 源于结构体字段未导出。牢记 Go 的反射与 JSON 规则——大写字母即公开,小写字母即私有。修正字段首字母大小写,即可让 result 正确落库、如期而至。










