go的net/rpc仅适用于同构go系统内部轻量通信,不支持跨语言、高并发、tls、负载均衡及生产级特性;跨语言调用必须改用jsonrpc或grpc等协议,否则会因gob编码、类型不匹配、连接静默断开等问题失败。

Go 的 net/rpc 只适合 Go 服务间轻量通信,跨语言调用必须换协议或框架,硬上会卡在 gob 解码、类型不匹配、连接静默断开这些地方。
方法签名和结构体字段必须全导出
服务端注册的结构体(如 Arith)和它的方法(如 Add)都得首字母大写;Args 和 Reply 结构体里每个字段也必须大写,否则 gob 编码时直接忽略,客户端收到空值或报 gob: type not found。
- 错误写法:
type args struct { A, B int }→ 字段小写,服务端收不到数据 - 正确写法:
type Args struct { A, B int }→ 字段导出,可被 gob 序列化 - 方法签名必须是
func(*T, *Args, *Reply) error,两个参数都得是指针,返回值只能是error - 接收者类型也要导出:
type Arith int✅,type arith int❌(小写类型无法注册)
HTTP 模式下路径和 handler 必须严格对齐
用 http.Serve 跑 RPC 时,rpc.HandleHTTP() 会自动注册 "/_goRPC_/" 和 "/_goRPC_/debug" 两个路径;但如果你手动调用 http.Handle,就得自己配对 —— 客户端 rpc.DialHTTP 发请求的 URL 路径,和服务端 http.Handle 绑定的路径,必须一字不差。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 服务端写
http.Handle("/rpc", rpc.DefaultServer),客户端就得用rpc.DialHTTP("tcp", "http://localhost:8080/rpc") - 用
rpc.DialHTTP("tcp", "localhost:8080/rpc")是错的:它会把"localhost:8080/rpc"当成 host,实际连去"localhost:8080/rpc:80",然后失败 - 浏览器访问
http://localhost:8080/_goRPC_/返回405 Method Not Allowed是正常现象 —— RPC 只响应 POST,不是 bug
gob 默认不跨语言,换 jsonrpc 也要两边同步改
net/rpc 默认走 gob,Python/Java 客户端连上去会卡在读取 magic number,报 invalid gob magic number 或直接 EOF。想跨语言,得切到 net/rpc/jsonrpc,但它只支持 TCP,不支持 HTTP 传输。
- 服务端不能只改 import,还得用
jsonrpc.NewServerCodec(conn)替换默认编解码器,再调server.ServeCodec(...) - 客户端必须用
jsonrpc.NewClientCodec(conn)构造 codec,再传给rpc.NewClient(...);混用rpc.Dial和 jsonrpc codec 会静默断连 -
jsonrpc不认自定义类型注册机制,所有字段必须是基础类型或标准 JSON 可序列化类型(比如不能用map[interface{}]interface{}) - HTTP + JSON 场景别指望
net/rpc/jsonrpc,它压根没实现 HTTP transport,得自己套一层 HTTP handler 或换 gRPC/REST
rpc.Client 不是并发安全的,别共享实例
多个 goroutine 共用一个 *rpc.Client 并发调用 Call,会竞争内部 seq 计数器和 response map,导致 panic 或返回错乱结果 —— 这不是偶发,是必然行为。
- 压测时容易触发
concurrent map read and map writepanic - 不要在 long-running server 里全局复用单个 client;TCP 连接可能因网络波动断开,client 不自动重连
- 安全做法:每个 goroutine 创建独立 client,或用
sync.Pool管理;若必须复用,得加互斥锁,但性能损失明显 - 记得
defer client.Close(),不关会导致文件描述符泄漏,too many open files是常见上线事故
最常被忽略的是:服务端注册了结构体,客户端却用错服务名(比如写成 "arith.Add" 而不是 "Arith.Add"),或者方法签名看着像对的,但第二个参数不是指针 —— 这类错误不会编译报错,只会在运行时返回 rpc: can't find service method,排查时容易绕远路。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










