不能。net/rpc 默认基于 TCP 二进制协议,不注册 HTTP handler,无法直接通过 HTTP 调用;需手动包装 HTTP handler 并配合 jsonrpc 或改用 gRPC/REST。

Go 的 net/rpc 能不能直接对外提供 HTTP RPC?
不能。默认的 net/rpc 是基于 TCP 的二进制协议,客户端必须用 Go 的 rpc.Client 连接,其他语言或 curl 根本没法调。有人试过用浏览器访问 :8080/_rpc_/,结果只看到 404 page not found —— 因为它压根没注册 HTTP handler。
- 如果真想走 HTTP,得手动包装:用
http.ServeMux注册一个路径,再把请求 body 交给rpc.Server.ServeCodec处理(比如配合rpc.NewHTTPClientCodec) - 更现实的做法是别硬扛:改用
net/rpc/jsonrpc+ 自定义 HTTP handler,或者直接切到 gRPC / REST -
net/rpc的 HTTP 支持仅限于内部调试用的rpc.DebugHTTP,它暴露的是服务统计页,不是可调用接口
为什么用 jsonrpc 时客户端总报 invalid character '?
这是典型的协议错配:客户端发的是 JSON-RPC 请求,但服务端监听的是原始 TCP,没做解码适配。Go 的 net/rpc 默认用 gob 编码,而 jsonrpc 是另一套独立的 codec 实现,必须显式启用。
- 服务端启动时不能只调
rpc.Register,还得用rpc.ServeCodec配合jsonrpc.NewServerCodec(通常封装在自定义 listener 里) - 客户端必须用
jsonrpc.NewClient或jsonrpc.NewClientCodec,不能用默认的rpc.Dial - 常见坑:误以为
rpc.Register后加个http.Handle("/rpc", rpc.Handler)就行——其实rpc.Handler只支持 gob,不认 JSON
方法签名不符合 func(*T, *S, *error) 会导致什么?
服务端启动不报错,但调用时返回 method XXX not found 或静默失败。Go 的 rpc.Server 在注册时只检查签名结构,不校验字段导出性或指针层级,等真正调用才反射匹配。
- 第一个参数必须是指针(
*T),代表接收者;第二个是输入参数指针(*S);第三个必须是*error类型,不能是error或其他名字的错误变量 - 所有参数结构体里的字段必须首字母大写(导出),否则 JSON/gob 编码会忽略它们,导致传参为空
- 返回值只能有且仅有三个,顺序不能换,类型不能松动——哪怕写成
*errors.Error也不行
要不要在生产环境用 net/rpc?
除非整个系统全是 Go 且对协议无扩展需求,否则不建议。它没有超时控制、流式响应、中间件、服务发现这些现代 RPC 必备能力,连 context 透传都要自己 hack。
立即学习 “go 语言免费学习笔记(深入)”;
- 内置的
gob编码不跨语言,jsonrpc又缺标准规范(比如无统一 error code、无 request id) - 连接复用靠客户端自己维护
*rpc.Client,服务端无法优雅关闭活跃连接 - 真正上线前你大概率要补日志、熔断、指标埋点——这些在 gRPC 或 Kitex 里是开箱即用的,而在
net/rpc里得一行行拧螺丝
最常被忽略的一点:它的错误传播机制是「全有或全无」——只要 handler 函数 panic,整个连接就断,且错误信息不会透传给客户端,只在服务端日志里留一行 goroutine stack trace。