Golang 实现一个简单的 RPC 服务

分享一个简单的 rpc 服务框架

一、服务端实现

Go 复制代码
package main

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

const HelloServiceName = "main.HelloService"

type HelloServiceInterface interface {
	Hello(request string, replay *string) error
}

func RegisterHelloService(svc HelloServiceInterface) error {
	//todo 其中 rpc.Register 函数调用会将对象类型中所有满足 RPC 规则的对象方法注册为 RPC 函数,所有注册的方法会放在 "HelloService" 服务空间之下。
	return rpc.RegisterName(HelloServiceName, svc)
}

type HelloService struct{}

//todo RPC方法需要满足的规则:只能有两个可序列化的参数,第二个参数表reply是指针类型,函数返回error类型,函数需要大写进行公开

func (p *HelloService) Hello(request string, reply *string) error {
	*reply = "hello:" + request
	return nil
}

func main() {
	//rpc.RegisterName("HelloService", new(HelloService))
	RegisterHelloService(new(HelloService))

	//todo 然后我们建立一个唯一的 TCP 连接,并且通过 rpc.ServeConn 函数在该 TCP 连接上为对方提供 RPC 服务。
	listener, err := net.Listen("tcp", ":1234")
	if err != nil {
		log.Fatal("ListenTCP error:", err)
	}

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Fatal("Accept error:", err)
		}

		//todo 启动协程去处理每个tcp请求
		go rpc.ServeConn(conn)
	}
}

二、客户端实现

Go 复制代码
package main

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

const HelloServiceName = "main.HelloService"

type HelloServiceInterface interface {
	Hello(request string, replay *string) error
}

type HelloServiceClient struct {
	*rpc.Client
}

// todo 在编译阶段检查 HelloServiceClient 类型是否实现了 HelloServiceInterface 接口。
// TODO 这里将 nil 转换为 *HelloServiceClient 类型并赋值给 _(匿名变量),编译器会自动检查 HelloServiceClient 是否实现了接口 HelloServiceInterface 中声明的所有方法。
// TODO 如果 HelloServiceClient 没有实现接口中的所有方法,这段代码会导致编译失败,从而在编码阶段就能发现潜在的问题。
var _ HelloServiceInterface = (*HelloServiceClient)(nil)

func DialHelloService(network, address string) (*HelloServiceClient, error) {
	c, err := rpc.Dial(network, address)
	if err != nil {
		return nil, err
	}

	return &HelloServiceClient{Client: c}, nil
}

func (p *HelloServiceClient) Hello(request string, reply *string) error {
	return p.Client.Call(HelloServiceName+".Hello", request, reply)
}

func main() {
	client, err := DialHelloService("tcp", "localhost:1234")

	if err != nil {
		log.Fatal("dialing:", err)
	}

	var reply string
	err = client.Hello("world", &reply)

	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(reply)
}
相关推荐
萧鼎19 小时前
Python 包管理的“超音速”革命:全面上手 uv 工具链
开发语言·python·uv
源代码•宸19 小时前
大厂技术岗面试之谈薪资
经验分享·后端·面试·职场和发展·golang·大厂·职级水平的薪资
Anastasiozzzz19 小时前
Java Lambda 揭秘:从匿名内部类到底层原理的深度解析
java·开发语言
刘琦沛在进步20 小时前
【C / C++】引用和函数重载的介绍
c语言·开发语言·c++
机器视觉的发动机20 小时前
AI算力中心的能耗挑战与未来破局之路
开发语言·人工智能·自动化·视觉检测·机器视觉
HyperAI超神经20 小时前
在线教程|DeepSeek-OCR 2公式/表格解析同步改善,以低视觉token成本实现近4%的性能跃迁
开发语言·人工智能·深度学习·神经网络·机器学习·ocr·创业创新
晚霞的不甘20 小时前
CANN 编译器深度解析:UB、L1 与 Global Memory 的协同调度机制
java·后端·spring·架构·音视频
R_.L20 小时前
【QT】常用控件(按钮类控件、显示类控件、输入类控件、多元素控件、容器类控件、布局管理器)
开发语言·qt
喵叔哟20 小时前
06-ASPNETCore-WebAPI开发
服务器·后端·c#
Zach_yuan20 小时前
自定义协议:实现网络计算器
linux·服务器·开发语言·网络