# golang rpc usage
## 引言
这个文章不对RPC的底层实现做深入剖析,也不讲解RPC是什么~~
## sample
RPC三步走,方法模型、服务端搭建、客户端设计
### model
我们以设计一个做加法运算的方法为例子
```
type Math int //Math类
type Args struct {
Ops1 int
Ops2 int
}
func (m *Math) Add(args Args, reply *int) error {
log.Print("server call Add")
*reply = args.Ops1 + args.Ops1
return nil
} ```
### server
```
func main() {
//创建对象
math := new(Math)
//rpc服务注册了一个Math对象 公开方法供客户端调用
_ = rpc.Register(math)
//指定rpc的传输协议 这里采用http协议作为rpc调用的载体 也可以用rpc.ServeConn处理单个连接请求
rpc.HandleHTTP()
l, e := net.Listen("tcp", ":8080")
if e != nil {
log.Fatal("listen error", e)
}
go http.Serve(l, nil)
_, _ = os.Stdin.Read(make([]byte, 1))//blocked
}
```
以上就是server的设计。
### client
```
//为了更规范编码,采用OOP思想进行封装
type MathCaller struct {
client *rpc.Client
Math//for overridge
}
//内置客户端
func NewHttpMathCaller(addr string) *MathCaller {
//调用rpc服务端提供的方法之前,先与rpc服务端建立连接
client, err := rpc.DialHTTP("tcp", addr)
if err != nil {
log.Fatal("dialHttp error", err)
return nil
}
mc := new(MathCaller)
mc.client = client
return mc
}
//同步调用
func (mc *MathCaller) Add(args Args, reply *int) error {
return mc.client.Call("Math.Add", args, reply)//通过这种方式,调用的时候,就类似于本地
}
```
### client main
```
func main(){
//调用rpc服务端提供的方法之前,先与rpc服务端建立连接
mc := rpcs.NewHttpMathCaller("127.0.0.1:8080")
//同步调用服务端提供的方法
args := &rpcs.Args{Ops1: 7, Ops2: 9}
var reply int
_ = mc.Add(*args, &reply)//调用封装后的RPC,看起来更像是调用本地的mathcaller的Add方法。
}
```
## 总结
以上的RPC sample只适用于golang的C/S之间的调用,因为底层使用了gob编码,并非是一种通用化编码,因此,如果要在golang与其它语言一块使用rpc,那么,可以使用gRPC+protubuf。或者是使用sonrpc这种基于json协议的RPC调用。
## Jsonrpc
基于jsonrpc,补充一个简单的demo.
```
func JsonRpcServer() error {
lis, err := net.Listen("tcp", ":1234")
if err != nil {
return err
}
defer lis.Close()
srv := rpc.NewServer()
//注册rpc对象
if err := srv.RegisterName("Math", new(Math)); err != nil {
return err
}
for {
conn, err := lis.Accept()
if err != nil {
log.Fatalf("lis.Accept(): %v\n", err)
}
go srv.ServeCodec(jsonrpc.NewServerCodec(conn))
}
}
```
```
func JsonClientRpc() {
client, err := jsonrpc.Dial("tcp", "127.0.0.1:1234") //tcp
if err != nil {
log.Fatal("dialing:", err)
}
args := &Args{Ops1: 7, Ops2: 9}
var reply int
err = client.Call("Math.Add", args, &reply)
if err != nil {
log.Fatal("rpc Math.xx err:", err)
}
fmt.Println("remote return:", reply)
}
```
有疑问加站长微信联系(非本文作者))