golang实现rpc方法一:使用net/rpc库【不能跨平台】

项目左侧包结构

rpc服务端实现

使用golang官方的net/rpc库实现RPC方法,使用http作为RPC的载体,通过http/net包监听客户端连接请求。

rpc服务端实现代码serverrpc.go如下

Go 复制代码
package main

import (
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/rpc"
	"os"
)

// 运算结构体
type Arith struct {
}

// 运算请求结构体
type ArithRequest struct {
	A int
	B int
}

// 运算响应结构体
type ArithResponse struct {
	Pro int  //product 表示乘积
	Quo int  //quotient 表示商
	Rem int  //remaind 表示余数
}

/*
	运算结构体的乘法运算方法
	第一个参数只需要拿到其里面的值只需要传一个结构体即可,
	第二个参数需要将运算结果存到其里面所以需要传地址
*/
func (this *Arith) Multiply(req ArithRequest, res *ArithResponse) error {
	res.Pro = req.A * req.B
	return nil
}

/*
	运算结构体的除法运算方法 
	第一个参数只需要拿到其里面的值只需要传一个结构体即可,
	第二个参数需要将运算结果存到其里面所以需要传地址
*/ 
func (this *Arith) Divide(req ArithRequest, res *ArithResponse) error {
	if req.B == 0 {  //除法为0,运算不合法
		return errors.New("divide by zero")
	}
	res.Quo = req.A / req.B
	res.Rem = req.A % req.B
	return nil
}
func main() {
	rpc.Register(new(Arith)) //注册rpc服务
	rpc.HandleHTTP()         //采用http作为rpc的载体

	lis, err := net.Listen("tcp", "127.0.0.1:8090") //Listen是block(阻塞的)
	if err != nil {
		log.Fatalln("fatal error:", err)
	}
	fmt.Fprintf(os.Stdout, "%s", "start connection")
	http.Serve(lis, nil) //net.Listen是阻塞的,需要通过这里进行启动
}

rpc客户端实现

上述服务端程序运行之后,将会监听本地的8090端口,我们可以实现一个客户端程序,连接服务端并且实现RPC方法调用。

rpc客户端实现代码clientrpc.go如下

Go 复制代码
package main

import (
	"fmt"
	"log"
	"net/rpc"
)

// 算数运算请求结构体
type ArithRequest struct {
	A int
	B int
}

// 算数运算响应结构体
type ArithResponse struct {
	Pro int  //product 乘积
	Quo int  //quotient 商
	Rem int  //remain 余数
}

func main() {
	//通过网络实现rpc远程进程调用
	conn, err := rpc.DialHTTP("tcp", "127.0.0.1:8090") 
	if err != nil {
		log.Fatalln("dailing error", err)
	}

	req := ArithRequest{9, 2}  //请求结构体
	var res ArithResponse    //响应结构体,用于存储运算结果

	//实现rpc之后,通过Call方法在客户端调用服务端里面算数运算结构体的乘法运算方法
	err = conn.Call("Arith.Multiply", req, &res)
	if err != nil {
		log.Fatalln("arith error", err)
	}
	fmt.Printf("%d * %d = %d\n", req.A, req.B, res.Pro)

	//实现rpc之后,通过Call方法在客户端调用服务端里面算数运算结构体的除法运算方法
	err = conn.Call("Arith.Divide", req, &res)
	if err != nil {
		log.Fatalln("arith error", err)
	}
	fmt.Printf("%d / %d, quo is %d, rem is %d\n", req.A, req.B, res.Quo, res.Rem)
}

详细实现步骤

1.首先初始化项目

bash 复制代码
go mod init pro01  //pro01表示项目名称

2.在当前项目下新建包server,并且在该包下面新建serverrpc.go实现rpc服务端

3.在当前项目下新建包client,并且在该包下面新建clientrpc.go实现rpc客户端

4.运行rpc服务端程序 ,首先进入server包,然后运行serverrpc.go

bash 复制代码
cd server
go run serverrpc.go

5.运行rpc客户端程序,首先进入client包,然后运行clientrpc.go

bash 复制代码
cd client
go run clientrpc.go

6.查看输出结果是否正确,输出结果如下表示程序运行结果正确,当然我这里的结果是根据我在请求结构体里面给出的俩个数值进行计算的,具体结果是否正确根据自己的具体程序判断。

总结:

通过官方库net/rpc实现rpc远程进程调用非常方便,并且实现还是比较简单的,但是有一个缺点就是不能跨平台。

相关推荐
懂点Tech9 小时前
ctfshow MISC入门图片篇(信息附加):misc41解题思路
开发语言·python
catchadmin10 小时前
PHP 8.7 协程新提案 让跨协程代码共享请求身份
开发语言·php
念何架构之路11 小时前
go-grpc设计思想
开发语言·后端·golang
酷炫码神11 小时前
Day 10|Pinia 状态管理:把散落在各组件的数据,收进一个全局仓库
android·开发语言·javascript
microrain11 小时前
SagooIoT 的缓存换后端只改一行配置,文件后端连 Redis 都不需要
物联网·缓存·golang·sagooiot
Elastic 中国社区官方博客12 小时前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn18812 小时前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn13 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
喵了几个咪13 小时前
GoWind ShortPlay 深度拆解:三服务 BFF + Core,一条请求的完整工程链路
golang·gowind
传奇开心果编程13 小时前
【Rust入门练中学】第5课:引用与借用
开发语言·rust·引用·编程语言理论·通用编程语言·借用