第一个rpc server
约 272 字小于 1 分钟
2024-07-20
Go net/rpc 客户端与服务端通信
这段代码演示了 Go 标准库 net/rpc 的基本用法,通过 TCP 建立 RPC 通信,实现一个简易的“rpc服务”
服务端 server.go
package main
import (
"errors"
"log"
"net"
"net/rpc"
)
type (
GetUserReq struct {
ID int `json:"id"`
}
GetUserResp struct {
ID int `json:"id"`
Name string `json:"name"`
}
)
type UserServer struct {
}
func (u *UserServer) GetUser(req *GetUserReq, resp *GetUserResp) error {
if user, ok := userList[req.ID]; ok {
// resp 在Server.readRequest就行了初始化(net/rpc/server.go)
resp.Name = user.Name
resp.ID = user.ID
return nil
}
return errors.New("user not found")
}
func main() {
err := rpc.Register(new(UserServer))
if err != nil {
log.Fatalln("rpc register error:", err)
}
listener, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatalln("listen error:", err)
}
log.Println("listening on :8080")
for {
conn, err := listener.Accept()
if err != nil {
log.Println("accept error:", err)
continue
}
go rpc.ServeConn(conn)
}
}
client
package main
import (
"log"
"net/rpc"
)
type (
GetUserReq struct {
ID int `json:"id"`
}
GetUserResp struct {
ID int `json:"id"`
Name string `json:"name"`
}
)
func main() {
client, err := rpc.Dial("tcp", "localhost:8080")
if err != nil {
log.Fatal("dialing:", err)
}
defer client.Close()
req := &GetUserReq{ID: 1}
resp := &GetUserResp{} // 不能直接定义 var resp *GetUserResp
// Call 的第三个参数必须是一个 可赋值的指针(即非 nil 的指针)
if err := client.Call("UserServer.GetUser", req, resp); err != nil {
log.Fatal("call error:", err)
}
log.Printf("%v\n", resp)
}