go 的 net/rpc 通过 http 协议提供远程过程调用,其底层依赖 http.server;而每个 rpc 请求均由 http.server 在独立 goroutine 中处理,因此服务端方法(如 multiply)总是在新启动的 goroutine 中执行,与主 goroutine 或其他请求完全隔离。
go 的 net/rpc 通过 http 协议提供远程过程调用,其底层依赖 http.server;而每个 rpc 请求均由 http.server 在独立 goroutine 中处理,因此服务端方法(如 multiply)总是在新启动的 goroutine 中执行,与主 goroutine 或其他请求完全隔离。
在你提供的服务端代码中:
func main() {
arith := new(Arith)
rpc.Register(arith)
rpc.HandleHTTP() // 注册 RPC 处理器到 http.DefaultServeMux
l, e := net.Listen("tcp", ":1234")
if e != nil {
log.Fatal("listen error:", e)
}
go http.Serve(l, nil) // 启动 HTTP 服务 —— 关键所在
}http.Serve(l, nil) 是实际承载 RPC 请求的入口。根据 http.Serve 的文档说明:
“Serve accepts incoming HTTP connections on the listener l, creating a new service goroutine for each. The service goroutines read requests and then call handler to reply to them.”
这意味着:每一个 TCP 连接(乃至更细粒度的每个 HTTP 请求)都会触发一个全新的 goroutine。由于 rpc.HandleHTTP() 将 RPC 处理逻辑注册到了 http.DefaultServeMux,当客户端发起 client.Call("Arith.Multiply", args, &reply) 时,该请求作为标准 HTTP POST(路径默认为 /rpc)被 http.Serve 捕获,并由专属 goroutine 调用 net/rpc 内部的请求分发器,最终执行你的 Multiply 方法。
✅ 因此:
- Multiply 一定运行在独立 goroutine 中,而非主线程或复用的 worker goroutine;
- 无需手动 go t.Multiply(...) —— 这由 http.Server 自动保障;
- 并发安全需由开发者自行保证(例如避免共享未加锁的全局状态)。
⚠️ 注意事项:
- rpc.HandleHTTP() 仅注册处理器,不会启动服务;必须显式调用 http.Serve(通常搭配 go 启动);
- 若使用自定义 ServeMux,需手动注册 rpc.HandleHTTP() 所绑定的路径(rpc.DefaultRPCPath 和 rpc.DefaultDebugPath);
- http.Serve 的并发模型是“每请求一 goroutine”,在高负载下需注意 goroutine 开销,必要时可结合 http.Server{MaxConns, IdleTimeout} 等参数做限流与超时控制。
总结:RPC 方法的执行天然具备并发性,这是 Go HTTP 栈的设计使然;你只需专注业务逻辑实现,goroutine 的生命周期与调度完全由 net/http 托管。

















