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,希望能为你的开发提供帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/427241.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java企业面试题2

1.语言的分代&#xff1a; 第1代&#xff1a;机器语言 机器语言是最底层的计算机编程语言&#xff0c;它是由二进制数构成的一系列指令&#xff0c;直接与计算机硬件交互。每个二进制位模式代表一条特定的指令或数据地址。因为它是直接在硬件上执行的&#xff0c;所以运行效率…

Java 23 的12 个新特性!!

Java 23 来啦&#xff01;和 Java 22 一样&#xff0c;这也是一个非 LTS&#xff08;长期支持&#xff09;版本&#xff0c;Oracle 仅提供六个月的支持。下一个长期支持版是 Java 25&#xff0c;预计明年 9 月份发布。 Java 23 一共有 12 个新特性&#xff01; 有同学表示&…

xmake与包管理:又一个现代c++构建工具?

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 主要起因是我在逛Reddit帖子时,看到关于一些c构建系统的评价. cmake似乎有些过于复杂,它与vcpkg,conan的包管理之间的"融合"可能在有些时候也显得麻烦. 一些人尝试了我没见过的选项, 所以这里主要试试除了…

Java重修笔记 第五十七天 坦克大战(七)多线程基础 - 编程练习

1. 线程之间的协调控制&#xff08;通知方式&#xff09; public class Homework04 {public static void main(String[] args) {// 在 main 方法中启动两个线程// 第一个线程内循环打印 1 到 100 以内的整数// 直到第二个线程从键盘读取到 "Q" 指令后结束第一个线程…

深入剖析大模型原理——Qwen Blog

1. 输入部分 Text&#xff1a;原始输入文本&#xff0c;模型需要处理的自然语言数据。Tokenizer&#xff1a;分词器&#xff0c;将输入文本转换为词汇表中的索引&#xff08;ID&#xff09;&#xff0c;便于后续处理。Input_ids&#xff1a;经过分词处理后的ID序列&#xff0c…

交流回馈老化测试负载的智能升级

在电子设备的生产过程中&#xff0c;老化测试是不可或缺的环节。老化测试主要是通过模拟设备长时间工作的情况&#xff0c;检测设备在经过一定时间的使用后&#xff0c;其性能是否会发生降低&#xff0c;是否存在安全隐患等。老化测试负载是老化测试中的重要组成部分&#xff0…

今日所学啊

ArcGIS打不开焦点统计如何解决_arcgis焦点统计打不开-CSDN博客 好吧其实最后焦点统计还是不行&#xff0c;我就去ArcGIS Pro里做焦点统计了哈哈哈哈哈哈哈 visual studio多工程项目管理_visual studio 的模块管理-CSDN博客 1.今天成功#include <QNetworkReply>不画红线…

【MYSQL表的增删改查(基础)】

MYSQL表的增删改查&#xff08;基础&#xff09; 一、CRUD二、新增&#xff08;Create&#xff09;2.1 单行数据全列插入2.2 多行数据指定列插入 三、查询&#xff08;Retrieve&#xff09;3.1 全列查询3.2 指定列查询3.3 查询字段为表达式3.3.1 表达式不包含字段3.3.2 表达式包…

react是什么?

文章目录 核心特点1. **组件化**2. **虚拟 DOM** 3. **声明式编程**4. **单向数据流**5. **JSX 语法**6. **Hooks** react的优势劣势 React 是一个由 Facebook 开发和维护的开源 JavaScript 库&#xff0c;用于构建用户界面&#xff0c;特别是单页应用程序&#xff08;SPA&…

[PICO VR眼镜]眼动追踪串流Unity开发与使用方法,眼动追踪打包报错问题解决(Eye Tracking/手势跟踪)

前言 最近在做一个工作需要用到PICO4 Enterprise VR头盔里的眼动追踪功能&#xff0c;但是遇到了如下问题&#xff1a; 在Unity里面没法串流调试眼动追踪功能&#xff0c;根本获取不到Device&#xff0c;只能将整个场景build成APK&#xff0c;安装到头盔里&#xff0c;才能在…

枚举(not二分)

前言&#xff1a;这一题似乎用不了二分以及三分&#xff0c;害我写这么久&#xff0c;但是查找下一个元素的时候要用到二分查找 题目地址 #include<bits/stdc.h> using namespace std; #define endl "\n"int n; const int N (int)2e510; vector<int> a;…

OceanBase 中 schema 的定义与应用

背景 经常在OceanBase 的问答社区 里看到一些关于 “schema 是什么” 的提问。 先纠正一些同学的误解&#xff0c; OceanBase 中的 Schema 并不简单的等同于 Database&#xff0c;本次分享将探讨 OceanBase 中的Schema是什么&#xff0c;及一些大家经常遇到的问题。 具体而…

JavaDS —— 图

图的概念 图是由顶点集合以及顶点之间的关系组成的一种数据结构&#xff1a;G &#xff08;V&#xff0c;E&#xff09; 其中 V 表示的是顶点集合 &#xff1a; V { x | x 属于某个数据对象集} 是有穷非空集合 E 叫做边的集合 &#xff1a; E {(x, y) | x, y 属于 V} 或者 …

UE5源码Windows编译、运行

官方文档 Welcome To Unreal Engine 5 Early Access Learn what to expect from the UE5 Early Access program. 链接如下&#xff1a;https://docs.unrealengine.com/5.0/en-US/Welcome/#gettingue5earlyaccessfromgithub Step 0&#xff1a;找到UE5源码 直接先上链接 https…

MySQL原理之UUID主键分析,插入或更新语法分析

文章目录 1 MySQL不能用UUID做主键1.1 前言1.2 mysql和程序实例1.2.1 准备工作1.2.2 开始测试1.2.3 程序写入结果1.2.4 效率测试结果 1.3 使用uuid和自增id的索引结构对比1.3.1 自增id1.3.2 uuid 1.4 自增id缺点1.5 雪花算法 2 插入或更新2.1 on duplicate key2.1.1 定义2.1.2 …

24年蓝桥杯及攻防世界赛题-MISC-3

21 reverseMe 复制图片&#xff0c;在线ocr识别&#xff0c;https://ocr.wdku.net/&#xff0c;都不费眼睛。 22 misc_pic_again ┌──(holyeyes㉿kali2023)-[~/Misc/tool-misc/zsteg] └─$ zsteg misc_pic_again.png imagedata … text: “$$KaTeX parse error: Undefined…

python基础(1)pyenv安装和对Django使用

pyenv安装 pyenv主要针对类 Unix 系统&#xff08;如 Linux、macOS&#xff09;用户&#xff0c;pyenv-win 是专为 Windows 开发的 pyenv 版本&#xff0c;允许您在不使用 WSL 的情况下管理多个 Python 版本和虚拟环境。 建议Git Bash&#xff1a; Powershell或Git Bash&…

功能测试干了三年,快要废了。。。

8年前刚进入到IT行业&#xff0c;到现在学习软件测试的人越来越多&#xff0c;所以在这我想结合自己的一些看法给大家提一些建议。 最近聊到软件测试的行业内卷&#xff0c;越来越多的转行和大学生进入测试行业&#xff0c;导致软件测试已经饱和了&#xff0c;想要获得更好的待…

Java键盘输入语句

编程输入语句 1.介绍:在编程中&#xff0c;需要接受用户输入的数据&#xff0c;就可以使用键盘输入语句来获取。 2.步骤&#xff1a; 1&#xff09;导入该类的所在包&#xff0c;java.util.* 2)创建该类对象&#xff08;声明变量&#xff09; 3&#xff09;调用里面的功能 3…

任务书与开题报告的区别与联系:如何让二者相辅相成

AIPaperGPT&#xff0c;论文写作神器~ https://www.aipapergpt.com/ 大家好&#xff01;今天咱们聊聊论文写作过程中两个让人又爱又恨的关键步骤&#xff1a;任务书和开题报告。 这两兄弟可是你毕业路上的第一关卡&#xff0c;搞不定它们&#xff0c;你后面别说论文了&#…