rpc, 个人理解就是调用不在一个机器上的方法。
jsonrpc就是调用过程中使用json格式的数据通信。
golang对jsonrpc有相应的标准库支持,记录一下如何使用。
测试代码结构(请根据自己实际目录调整):
[root@gl jsonrpc]# tree
.
├── client
│ └── client.go
├── main.go
└── server
├── calc.go
└── cmd
└── main.go
calc.go:
package server
import (
"fmt"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
)
type Calc struct{}
type Args struct {
A float64 `json:"a"`
B float64 `json:"b"`
Op string `json:"op"`
}
type Reply struct {
Msg string `json:"msg"`
Data float64 `json:"data"`
}
// func (t *T) MethodName(argType T1, replyType *T2) error
// 一定要满足这种格式, 其中replyType要为指针。并注意大小写
func (c *Calc) Compute(args Args, reply *Reply) error {
var (
msg string = "ok"
)
switch args.Op {
case "+":
reply.Data = args.A + args.B
case "-":
reply.Data = args.A - args.B
case "*":
reply.Data = args.A * args.B
case "/":
if args.B == 0 {
msg = "in divide op, B can't be zero"
} else {
reply.Data = args.A / args.B
}
default:
msg = fmt.Sprintf("unsupported op:%s", args.Op)
}
reply.Msg = msg
if reply.Msg == "ok" {
return nil
}
return fmt.Errorf(msg)
}
// 启动server端
func Start() {
err := rpc.Register(new(Calc))
if err != nil {
panic(err)
}
listener, err := net.Listen("tcp", "127.0.0.1:8888")
if err != nil {
panic(err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Println(err)
continue
}
go jsonrpc.ServeConn(conn)
}
}
server/cmd/main.go:
package main
// 具体情况要调整这里的路径
import "gerrylon.top/learnGo/jsonrpc/server"
func main() {
server.Start()
}
client.go(这个只是做了一个封装,方便调用):
package client
import (
"fmt"
"gerrylon.top/learnGo/jsonrpc/server"
"log"
"net/rpc/jsonrpc"
)
func Call(args server.Args, reply *server.Reply) error {
conn, err := jsonrpc.Dial("tcp", "127.0.0.1:8888")
if err != nil {
log.Fatalln("dailing error: ", err)
return err
}
defer conn.Close()
// 调用远程的Calc的Compute方法
err = conn.Call("Calc.Compute", args, &reply)
return err
}
main.go:
package main
import (
"fmt"
"gerrylon.top/learnGo/jsonrpc/client"
"gerrylon.top/learnGo/jsonrpc/server"
)
func main() {
args := server.Args{
A: 1,
B: 2,
Op: "+",
}
var reply server.Reply
err := client.Call(args, &reply)
display(err, args, reply)
args = server.Args{
A: 1, B: 0, Op: "/",
}
err = client.Call(args, &reply)
display(err, args, reply)
}
func display(err error, args server.Args, reply server.Reply) {
if err != nil {
fmt.Printf("err:%v\n", err)
} else {
// 如果err不为nil,这里的reply是上个调用的值
// 因此可能会出现1.00 / 0.00=3.00
fmt.Printf("%.2f %s %.2f=%.2f\n", args.A, args.Op, args.B, reply.Data)
}
}
输出:
1.00 + 2.00=3.00
err:in divide op, B can’t be zero
func (t *T) MethodName(argType T1, replyType *T2) error
这种格式参考:
https://www.jianshu.com/p/98a84a6339b7
欢迎补充指正!