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 框架遵循以下几条规则:
- 服务对象是公开的结构体类型。
- 服务对象的方法必须是公开的,并且方法必须有两个参数和一个返回值。第一个参数是输入参数,第二个参数是指针类型用于接收返回结果,返回值是
error
类型。 - 客户端通过
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
结构体,它有两个方法 Multiply
和 Divide
,分别用于乘法和除法运算。
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
函数连接到服务端。连接建立后,客户端调用远程的 Multiply
和 Divide
方法,并输出结果。
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,希望能为你的开发提供帮助。
相关文章:
Go 中 RPC 的使用教程
前言 RPC(Remote Procedure Call)是一种允许程序调用远程服务器上函数的方法,调用过程对于开发者来说像是调用本地函数一样方便。Go 语言自带了强大的 net/rpc 库,能够让开发者轻松实现基于 Go 的 RPC 服务。本文将介绍 Go 中 RP…...

挖耳勺可以伸进耳朵多深?安全可视挖耳勺推荐!
一般来说,挖耳勺不应该伸进耳朵太深,外耳道的长度大约在2.5厘米到3.5厘米之间,但不建议将挖耳勺伸进超过外耳道外1/3的深度,也就是大概1厘米左右较为安全。因为如果伸得太深,很容易损伤外耳道皮肤,引起疼痛…...

SuperMap GIS基础产品FAQ集锦(20240911)
一、SuperMap iObjects Java 问题1:【iObject Python】Objects Python产品有哪些能力特性和优势? 11.2.0 【解决办法】iObjects Python产品包含传统GIS功能(基于iObjects Java扩展的功能接口)和AI GIS功能模块。 其中传统GIS功能…...
从状态管理到性能优化:全面解析 Android Compose
文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compo…...
ChatGPT提示词优化大师使用指南
我希望你成为我的ChatGPT提示词优化大师。 您的目标是帮助我根据自己的需要制定尽可能最好的提示。 你提供的提示应该是站在我向ChatGPT发起请求的角度来写的。我的初始提示词如下:此处填入你的初始提示词 ChatGPT提示词生成器 我希望你充当提示词生成器。 比如&…...

计算机毕业设计 智能推荐旅游平台 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试
🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...
【拥抱AI】基于多种数据分段工具的优缺点分析
最近在深入了解RAG方面的知识,其中数据清洗和数据分段是创建知识库的重要步骤。数据清洗目前暂时选用了MinerU,然后就需要针对数据分段进行选型。 以下是我了解到的几种数据分段工具,简单总结了一下它们的优缺点,权当笔记分享&am…...

在 Windows 系统上,文件传输到虚拟机(VM)可以通过 VS Code 的图形界面(GUI)或命令行工具进行操作
在 Windows 系统上,文件传输到虚拟机(VM)可以通过 VS Code 的图形界面(GUI)或命令行工具进行操作。以下是几种方法: ### 方法 1: 使用 VS Code 图形界面 1. **连接到远程 VM**: - 在 VS Cod…...
kafka的主要功能
Apache Kafka 是一个分布式流处理平台,它最初由 LinkedIn 开发,后来捐赠给了 Apache Software Foundation,并成为了 Apache 的顶级项目。Kafka 设计用于处理实时数据流,并且提供了高性能、可扩展性和持久性。下面是 Kafka 的主要功…...
vue3中provide和inject详解
provide和inject是什么 provide 和 inject 是 Vue.js 框架中提供的一种依赖注入机制。这种机制允许一个祖先组件(提供者)向其所有子孙组件(使用者)提供数据或方法,而不需要通过逐层组件传递属性(props&…...

相约华中科技大学,移动云技术论坛来了!NineData创始人CEO叶正盛将分享《数据库全球实时传输技术实践》的主题演讲
2024年9月12日,中国移动云能力中心将在华中科技大学举办“智算浪潮下数据库发展论坛”,共同探讨数据库技术与应用的创新,分享算力网络时代数据库未来发展的洞见。本次论坛,NineData 创始人&CEO 叶正盛受邀参会,并来…...

华为 昇腾 310P 系列 AI 处理器支持 140Tops 的 AI 算力。
1、产品简介 模组是基于昇腾 310P 系列 AI 处理器设计而成,可实现图像、视频等多种数据分析 与推理计算。超强的视频编解码能力以及支持 140Tops 的 AI 算力。在边缘侧及端侧的嵌入式计算 领域,有着极高的性价比,具有超强算力、 超高能效、…...

基于单片机的小型生态鱼缸控制器设计
本设计以STC89C52单片机为核心,利用DS18B20温度传感器和LCD1602液晶显示器实时采集和显示当前环境温度,并根据与预设温度阈值的比较结果控制加热棒或风扇进行加热或制冷操作。此外,该控制器还利用DS1302完成计时功能,在预设时间点…...
git-repo使用
即使用 XML 格式文件(manifest 清单文件)定义一个项目的多仓库关联,然后用 repo 客户端工具操作多仓库 git repo命令行格式: git repo <子命令> <参数>创建一个空目录,作为工作区。 $ mkdir workspace$ …...
如何设计实现完成一个FPGA项目
设计并完成一个FPGA项目是一个复杂但非常有价值的工程任务。以下是一个详细的步骤指南,帮助你从零开始完成一个FPGA项目。 1. 项目定义与需求分析 确定项目目标:明确项目要实现的功能和性能指标。需求分析:列出所有功能需求、性能需求、接口需求等。可行性分析:评估技术可…...
Oracle(106)如何实现透明数据加密?
透明数据加密(TDE)是一种用于保护数据库中静态数据的加密技术。TDE通过自动加密数据库文件和日志文件,确保数据在磁盘上是加密的,从而防止未经授权的访问。TDE的一个主要优点是它对应用程序是透明的,不需要对应用程序代…...

用Python实现时间序列模型实战——Day 18: 时间序列中的季节性与周期性预测
一、学习内容 1. 季节性调整与周期性预测 季节性调整 是在时间序列分析中常用的技术,旨在去除数据中因季节性波动导致的周期性变化,使数据更易于解释和预测。通常,我们可以使用季节性分解方法来分离时间序列中的趋势、季节性和随机成分。 …...

JavaScript ES6特性(var let const、function=>、增强表达赋值、类与对象)
一、var let const 1、var var明明定义在for里面的但是外部能够访问这个变量,说明var可以跨域访问。 2、let let明明定义在for里面的但是外部不能够访问这个变量,说明let不可以跨域访问。 3、const const foo = {}; // 为 foo 添加一个属性,可以成功 foo.prop = 123; fo…...
Paddle安装详解(CPU版本)
目录 1. 安装Python2. 安装paddle3. 验证3.1 初步验证3.2 将numpy版本从2.1.1降为2.0.13.3 再次验证1. 安装Python Python版本 C:\Users\james>python --version Python 3.12.62. 安装paddle 安装paddle及依赖库setuptools python -m pip install paddlepaddle==2.6.1 -…...

PHP即刻送达同城派送小程序系统
即刻送达,同城派送小程序系统让生活更便捷 🚀 瞬间连接,即刻送达的奇迹 你是否曾经因为等待快递而焦急万分?是否渴望有一种方式能让物品像魔法一样瞬间出现在你面前?现在,有了“即刻送达同城派送小程序系…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...