当前位置: 首页 > news >正文

Go 中 RPC 的使用教程

前言

RPC(Remote Procedure Call)是一种允许程序调用远程服务器上函数的方法,调用过程对于开发者来说像是调用本地函数一样方便。Go 语言自带了强大的 net/rpc 库,能够让开发者轻松实现基于 Go 的 RPC 服务。本文将介绍 Go 中 RPC 的使用方法,并通过简单示例展示如何搭建 RPC 服务和客户端。


一、什么是 RPC?

RPC(远程过程调用)是一种跨网络通信协议,允许程序在不同的主机上执行代码而不需要明确处理底层网络通信。使用 RPC,开发者只需编写服务端的逻辑,然后客户端可以像调用本地函数一样调用服务端的函数,底层的网络传输、序列化和反序列化都由 RPC 框架处理。

在 Go 中,RPC 是通过 net/rpc 包实现的,Go 标准库还支持 JSON-RPC 和 HTTP 传输协议。


二、Go 中 RPC 的基本原理

Go 中的 RPC 框架遵循以下几条规则:

  1. 服务对象是公开的结构体类型。
  2. 服务对象的方法必须是公开的,并且方法必须有两个参数和一个返回值。第一个参数是输入参数,第二个参数是指针类型用于接收返回结果,返回值是 error 类型。
  3. 客户端通过 net/rpc 库向服务端发出请求,服务端执行对应的函数,返回结果。

三、Go 中 RPC 的使用步骤

1. 定义服务

首先,我们需要定义一个服务。这个服务是一个 Go 结构体,其中包含一些方法供客户端调用。

package mainimport ("errors""net""net/rpc""fmt"
)// 定义服务结构体
type Arith struct{}// 定义输入参数
type Args struct {A, B int
}// 定义服务方法
func (t *Arith) Multiply(args *Args, reply *int) error {*reply = args.A * args.Breturn nil
}func (t *Arith) Divide(args *Args, reply *int) error {if args.B == 0 {return errors.New("divide by zero")}*reply = args.A / args.Breturn nil
}

在上面的代码中,我们定义了 Arith 结构体,它有两个方法 MultiplyDivide,分别用于乘法和除法运算。

2. 启动 RPC 服务

接下来,我们需要启动一个 RPC 服务器,让客户端可以通过网络调用这个服务。

func main() {arith := new(Arith)rpc.Register(arith)  // 注册服务listener, err := net.Listen("tcp", ":1234")  // 监听端口if err != nil {fmt.Println("Error starting server:", err)}fmt.Println("Server is listening on port 1234...")for {conn, err := listener.Accept()  // 接收连接if err != nil {fmt.Println("Error accepting connection:", err)continue}go rpc.ServeConn(conn)  // 使用 goroutine 处理每个连接}
}

这段代码启动了一个监听在 1234 端口的 RPC 服务器。每当有客户端请求连接时,服务器会处理该连接并执行相应的 RPC 方法。

3. 创建 RPC 客户端

服务端已经准备好了,接下来我们需要编写客户端代码,客户端将通过 RPC 远程调用服务端的函数。

package mainimport ("fmt""log""net/rpc"
)type Args struct {A, B int
}func main() {client, err := rpc.Dial("tcp", "localhost:1234")  // 连接服务端if err != nil {log.Fatal("dialing:", err)}// 调用 Multiply 方法args := Args{A: 7, B: 8}var reply interr = client.Call("Arith.Multiply", args, &reply)if err != nil {log.Fatal("arith error:", err)}fmt.Printf("Arith: %d * %d = %d\n", args.A, args.B, reply)// 调用 Divide 方法args = Args{A: 10, B: 2}err = client.Call("Arith.Divide", args, &reply)if err != nil {log.Fatal("arith error:", err)}fmt.Printf("Arith: %d / %d = %d\n", args.A, args.B, reply)
}

在这段代码中,客户端首先通过 rpc.Dial 函数连接到服务端。连接建立后,客户端调用远程的 MultiplyDivide 方法,并输出结果。

4. 运行程序

首先在一个终端启动服务端:

go run server.go

然后在另一个终端运行客户端:

go run client.go

运行后,客户端会输出类似以下内容:

Arith: 7 * 8 = 56
Arith: 10 / 2 = 5

四、Go 中的 RPC 进阶

1. 异步调用

Go 的 RPC 框架支持异步调用,可以通过 Go 方法实现。它会返回一个 Call 对象,通过该对象可以获取异步调用的结果。

call := client.Go("Arith.Multiply", args, &reply, nil)
replyCall := <-call.Done  // 等待结果
fmt.Printf("Async result: %d * %d = %d\n", args.A, args.B, replyCall.Reply)

2. 使用 HTTP 作为传输协议

Go 也支持通过 HTTP 协议进行 RPC 通信,只需稍加配置:

rpc.HandleHTTP()
listener, err := net.Listen("tcp", ":1234")
go http.Serve(listener, nil)

在客户端中,通过 rpc.DialHTTP 连接服务端:

client, err := rpc.DialHTTP("tcp", "localhost:1234")

五、总结

通过 net/rpc,Go 提供了一个简单而高效的 RPC 实现。它让开发者可以轻松地构建分布式系统,并且底层的通信和序列化都由库自动处理,极大地降低了开发复杂性。本文通过一个简单的示例展示了如何在 Go 中使用 RPC,希望能为你的开发提供帮助。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 用网卡的ap模式抓嵌入式设备的网络包
  • python+adb
  • PHP即刻送达同城派送小程序系统
  • 数据分析-螺旋环状气泡图
  • 针对SVM算法初步研究
  • 【TabBar嵌套Navigation案例-复习昨天的内容-预习今天的内容 Objective-C语言】
  • 【数据结构】线性表的定义和基本操作
  • Java零基础-charAt(int index)详解
  • 从零实现诗词GPT大模型:实现多头自注意力
  • 如何使用命令行快速下载Google Drive/OneDrive大文件
  • 【时间盒子】-【6.任务页面】在同一个页面新建、编辑任务
  • 阳极氧化废酸处理
  • 陶建辉演讲干货分享,AI 时代下的数据预测和数据处理挑战
  • PL/SQL 继承Oracle Database 的可靠性、安全性和可移植性
  • Note24091201_组态王画面按钮静音设置
  • 2017 前端面试准备 - 收藏集 - 掘金
  • fetch 从初识到应用
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • httpie使用详解
  • isset在php5.6-和php7.0+的一些差异
  • nodejs:开发并发布一个nodejs包
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 程序员最讨厌的9句话,你可有补充?
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 简单基于spring的redis配置(单机和集群模式)
  • 世界上最简单的无等待算法(getAndIncrement)
  • 数组大概知多少
  • 以太坊客户端Geth命令参数详解
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • 主流的CSS水平和垂直居中技术大全
  • postgresql行列转换函数
  • 阿里云移动端播放器高级功能介绍
  • 函数计算新功能-----支持C#函数
  • 容器镜像
  • ​【已解决】npm install​卡主不动的情况
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • ​经​纬​恒​润​二​面​​三​七​互​娱​一​面​​元​象​二​面​
  • "无招胜有招"nbsp;史上最全的互…
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • #QT(QCharts绘制曲线)
  • (2)MFC+openGL单文档框架glFrame
  • (4)Elastix图像配准:3D图像
  • (C++)八皇后问题
  • (Qt) 默认QtWidget应用包含什么?
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • .Net 4.0并行库实用性演练
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .net core webapi 大文件上传到wwwroot文件夹
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端