Go标准库net/rpc/jsonrpc非独立包,需配合net/rpc使用;支持跨语言调用但仅实现JSON-RPC 1.0,方法签名、字段导出、连接管理等细节需严格遵循规范。

Go 标准库的 net/rpc/jsonrpc 不是独立包,也不能直接 go get 安装;它只是 net/rpc 的一个编解码器实现,必须配合 net/rpc 使用。跨语言调用可行,但协议细节、错误处理和连接生命周期需手动兜底。
服务端必须注册导出类型并满足 RPC 方法签名约束
Go 的 net/rpc 对方法签名有硬性要求:接收者类型必须导出、方法名必须导出、两个参数都必须是导出类型(或内置类型)、第二个参数必须是指针、返回值必须是 error。不满足任一条件,客户端调用会报 rpc: can't find service method。
-
func (s *Service) DoSomething(req Request, reply *Response) error✅ 正确(req是值传入,reply是指针输出) -
func (s *Service) DoSomething(req *Request, reply *Response) error❌ 错误(第一个参数不能是指针) -
func (s *service) DoSomething(...)❌ 错误(接收者类型service未导出) -
type request struct { ID int }❌ 错误(字段ID小写,未导出,JSON 编解码后为null)
结构体字段也必须首字母大写,并显式加 json: tag(如 ID int `json:"id"`),否则 jsonrpc 编解码时无法映射。
客户端 Dial 后必须用 Call 而非 Go,且参数顺序不能颠倒
jsonrpc 客户端不支持异步调用(Go 方法在 jsonrpc.ClientCodec 下被禁用),所有调用必须阻塞等待响应。调用时传参顺序固定:service.method(字符串,如 "Arith.Multiply")、请求参数(值或指针,按方法定义)、响应指针(必须是指针)。
立即学习“go语言免费学习笔记(深入)”;
-
err := client.Call("Arith.Multiply", &args, &reply)✅ 正确 -
err := client.Call("Multiply", args, &reply)❌ 错误(服务名缺前缀,参数不是地址) -
err := client.Call("Arith.Multiply", args, reply)❌ 错误(第三个参数必须是指针)
如果服务端返回了 error(非 nil),Call 仍返回 nil,但 reply 可能为零值 —— 真实错误藏在 JSON 响应的 error 字段里,需检查 reply 内容或日志。
TCP 连接需手动管理,不支持自动重连或超时控制
jsonrpc.ServeConn 是单次连接单次服务模型:一个 TCP 连接只处理一批请求,连接断开即终止。没有内置心跳、重试、超时或连接池。常见问题包括:
- 客户端短连接频繁
Dial→ 服务端accept+ServeConn开销高 - 网络抖动导致连接中断 → 客户端
Call卡住或返回io.EOF,无重试逻辑 - 服务端未设
SetDeadline→ 连接可能长期 hang 住,耗尽文件描述符
实际部署中,应在 conn 上设置读写 deadline(如 conn.SetReadDeadline(time.Now().Add(5 * time.Second))),并在 for 循环中捕获 net.ErrClosed 或 io.EOF 后主动关闭连接。
跨语言调用时 JSON-RPC 2.0 兼容性有限
Go 标准库 net/rpc/jsonrpc 实现的是 JSON-RPC 1.0 规范(无 jsonrpc 版本字段、不校验 id 类型、不支持通知请求)。与主流 JSON-RPC 2.0 客户端(如 Python 的 jsonrpclib、JS 的 jayson)交互时,容易出现:
- 服务端忽略客户端发来的
"jsonrpc": "2.0"字段,但仍按 1.0 解析 - 客户端期待
result或error二选一,而 Go 默认两者都存在(error: null)→ 某些解析器报错 - 批量请求(batch)完全不支持
若需真正跨语言且符合 2.0 规范,应避免 net/rpc/jsonrpc,改用 gorilla/rpc、go-jsonrpc(第三方)或直接基于 net/http + encoding/json 手写 endpoint。
真正麻烦的从来不是“怎么连上”,而是连接断了谁来关、错误是服务端抛的还是网络丢的、字段大小写漏了一个 tag 导致整个请求静默失败 —— 这些细节不会报错,只会让 reply 为空、日志无声、调试三小时。


















