
Go 的 net/rpc 为什么连本地调用都失败?
默认只支持导出(首字母大写)的方法,且必须满足签名:func(*T, *Arg, *Reply) error。常见错误是方法没导出、参数不是指针、或返回值类型不对。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
-
Arg和Reply类型必须可被gob编码(即字段导出、不包含 channel/func/map[非字符串键] 等) - 服务端注册的是结构体指针:
rpc.Register(new(MyService)),不是值类型 - 客户端调用前必须确保服务端已启动并监听,且网络可达(哪怕 localhost 也要检查防火墙或端口占用)
- 错误信息如
rpc: can't find service MyService.Method,大概率是方法未导出或注册名不匹配
用 jsonrpc 替换 gob 时连接直接断开?
net/rpc 默认用 gob 编码,换 jsonrpc 需显式切换客户端和服务端的编解码器,两边不一致就会静默断连。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 服务端改用
rpc.ServeCodec(jsonrpc.NewServerCodec(conn)),而不是rpc.ServeConn - 客户端对应使用
rpc.DialHTTP("tcp", addr)或手动构造jsonrpc.NewClientCodec,不能混用rpc.Dial -
jsonrpc不支持gob的自定义类型注册机制,所有字段必须是基础类型或标准库支持的 JSON 可序列化类型 - 注意 HTTP transport 层的超时和 Keep-Alive 设置,
jsonrpc基于 HTTP,容易因长连接复用问题卡住
并发调用 rpc.Client.Call 为啥总 panic?
rpc.Client 实例**不是并发安全的**。多个 goroutine 共享一个 *rpc.Client 并发调用 Call 或 Go,会竞争内部的 seq 计数器和响应 map,导致 panic 或错乱响应。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 每个 goroutine 应该用独立的
*rpc.Client实例,或用连接池(如sync.Pool管理) - 更稳妥的做法是封装一层 client factory:
func NewRPCClient(addr string) *rpc.Client,按需创建 - 不要在 long-running server 中长期持有单个
rpc.Client;它底层 TCP 连接可能因网络波动断开,而Client不自动重连 - 如果必须复用,加互斥锁保护
Call调用 —— 但性能会显著下降,不如换 gRPC 或其他带连接管理的框架
为什么 net/rpc 在跨语言场景下几乎不可用?
因为 net/rpc 协议本身没有公开规范,gob 是 Go 私有编码格式,jsonrpc 子包也只实现了 HTTP + JSON 的简单封装,缺少服务发现、版本协商、错误码标准化等能力。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 别指望 Python/Java 客户端能直连 Go 的
net/rpc服务,除非你手写完整协议解析器 - 对外暴露接口时,优先考虑 REST/HTTP+JSON,或用 gRPC(IDL + 多语言 stub)
- 若坚持用
net/rpc,仅限内部、同构 Go 服务间轻量通信;上线前务必压测连接泄漏和 goroutine 泄漏(rpc.Server默认无并发限制) - 注意
rpc.Server的Shutdown方法是实验性 API(Go 1.21+),旧版本需自行管理 listener 和 conn 生命周期
真正麻烦的不是怎么写通,而是连接生命周期、错误传播路径、以及——没人告诉你 rpc.Client 里那个 mutex 锁在哪,直到它开始丢响应。










