go http rpc
1 服务端
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "errors" "fmt" "net/http" "net/rpc" ) type Args struct { A, B int } type Quotient struct { Quo, Rem int } type Arith int func (t *Arith) Multiply(args *Args, reply *int) error { *reply = args.A * args.B return nil } func (t *Arith) Divide(args *Args, quo *Quotient) error { if args.B == 0 { return errors.New("除数不能为0") } quo.Quo = args.A / args.B quo.Rem = args.A % args.B return nil } // 注册了一个Arith的RPC服务, func main() { arith := new(Arith) rpc.Register(arith) // 把该服务注册到HTTP协议上, rpc.HandleHTTP() err := http.ListenAndServe(":1234", nil) if err != nil { fmt.Println(err.Error()) } }
2 客户端
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package main import ( "fmt" "log" "net/rpc" "os" ) type Args struct { A,B int } type Quotient struct { Quo, Rem int } func main() { fmt.Println(os.Args) if len(os.Args) != 2{ fmt.Println("用法:", os.Args[0], "server") // Exit 函数可以让当前程序以给出的状态码 code 退出。一般来说,状态码 0 表示成功, // 非 0 表示出错。程序会立刻终止,并且 defer 的函数不会被执行。 os.Exit(1) } // 服务器地址 serverAddress := os.Args[1] // 指定通信协议是tcp,并且指定IP地址和端口号, client, err := rpc.DialHTTP("tcp", serverAddress+":1234") if err != nil{ log.Fatalf("Dial错误",) } // Synchronous call args := Args{17, 8} var reply int // 第一个参数是要具体调用的函数的名称,Arith是服务端注册的服务名, // 第二个参数是要传递给服务端的参数, // 第三个参数是要服务端返回的结果,注意是指针类型, err = client.Call("Arith.Multiply", args, &reply) if err != nil{ log.Fatal("arith错误:", err) } fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply) var quot Quotient err = client.Call("Arith.Divide", args, ") if err != nil{ log.Fatal("arith错误:", err) } fmt.Printf("Arith: %d/%d=%d 余 %d\n", args.A, args.B, quot.Quo, quot.Rem) }
客户端的Call输入三个参数,服务端返回两个参数,