Go中如何跨语言实现传输? - GRPC

Go中如何跨语言实现传输? - GRPC

gRPC 是 Google 开源的高性能 RPC 框架,基于 HTTP/2 协议和 Protocol Buffers(Protobuf)序列化,支持多语言、流式传输和企业级特性。与 RESTful API 相比,它性能更高、接口定义更规范,特别适合微服务架构和跨语言服务调用。

概念 作用 说明
Protocol Buffers(Protobuf) 接口定义语言(IDL) 用于定义服务接口和消息结构,跨语言、跨平台,序列化性能极高
Service(服务) 定义 RPC 方法 .proto 文件中定义,包含方法名、请求消息、响应消息
Message(消息) 定义数据结构 类似于 Go 的结构体,用于定义请求和响应的数据格式
Unary RPC(一元 RPC) 最简单的 RPC 模式 客户端发送一个请求,服务端返回一个响应,类似传统的 HTTP 请求
Server Streaming RPC(服务端流式) 服务端流式返回 客户端发送一个请求,服务端返回多个响应
Client Streaming RPC(客户端流式) 客户端流式发送 客户端发送多个请求,服务端返回一个响应
Bidirectional Streaming RPC(双向流式) 双向流式传输 客户端和服务端可以同时发送和接收多个消息
bash 复制代码
# 1. 安装 protoc 编译器
# Mac 
brew install protobuf 
# Linux 
apt install -y protobuf-compiler

# 2. 安装 Go 插件
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
# 3. 安装 gRPC 核心库
go get google.golang.org/grpc

Unary RPC (一元 RPC)

plaintext 复制代码
grpc-demo/
├── proto/ 
│ └── user.proto # Protobuf 定义文件 
├── server/ 
│ └── main.go # gRPC 服务端
├── client/ 
│ └── main.go # gRPC 客户端 
└── go.mod

编写 Protobuf 定义(proto/user.proto

这是 gRPC 开发的核心,定义接口契约。

protobuf 复制代码
// 指定 Protobuf 版本 
syntax = "proto3"; 
// 指定生成的 Go 代码的包路径 
option go_package = "./proto"; 
// 定义包名 
package user;

// 定义消息(数据结构)
message User {
  uint32 id = 1; // 字段编号:1-15 占 1 字节,常用字段优先
  string username = 2;
  string email = 3;
}

message GetUserRequest {
  uint32 user_id = 1;
}

message GetUserResponse {
  User user = 1;
}

// 定义服务
service UserService {
  // 一元 RPC 方法
  rpc GetUser(GetUserRequest) returns (GetUserResponse);
}
  • syntax = "proto3"; :指定使用 Protobuf v3 版本(推荐,比 v2 更简洁)。

  • option go_package = "./proto"; :指定生成的 Go 代码的包路径。

  • 消息字段编号:每个字段必须有唯一的编号,1-15 占 1 字节,16-2047 占 2 字节,常用字段建议用 1-15。

  • service Xxx { rpc Yyy(Req) returns (Resp) }:定义服务,包含多个 RPC 方法。

  • rpc 方法名(请求) returns (响应) :定义 RPC 方法。

  • message Xxx { type field = tag; }:定义消息结构,tag 必须唯一

bash 复制代码
protoc --go_out=. --go-grpc_out=. proto/user.proto

执行成功后,会在 proto/ 目录下生成两个文件:

  • user.pb.go:消息结构的 Go 代码
  • user_grpc.pb.go:服务接口的 Go 代码

服务端实现

go 复制代码
import (pb "grpc-demo/proto")

// 定义服务结构体,必须嵌入 Unimplemented*Server
type UserServer struct {
	pb.UnimplementedUserServiceServer // 必须嵌入,保证向前兼容
}

// 实现 Protobuf 中定义的 RPC 方法
func (s *UserServer) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.GetUserResponse, error) {
	// 核心业务逻辑:查询数据库等
	user := &pb.User{
		Id:       req.UserId,
		Username: "zhangsan",
		Email:    "zhangsan@example.com",
	}
	return &pb.GetUserResponse{User: user}, nil
}

func main() {
	// 监听端口
	lis, _ := net.Listen("tcp", ":50051")
	// 创建 gRPC 服务器
	s := grpc.NewServer()
	// 将服务实现注册到 gRPC 服务器
	pb.RegisterUserServiceServer(s, &UserServer{})
	// 启动服务,监听 TCP 连接
	s.Serve(lis)
}
  • type XxxServer struct { pb.UnimplementedXxxServer }:定义服务结构体,必须嵌入 Unimplemented

  • pb.UnimplementedUserServiceServer:必须嵌入这个结构体,确保向前兼容,即使后续服务添加了新方法,旧的服务端代码也不会报错。

  • 实现服务接口 :必须实现 .proto 文件中定义的所有 RPC 方法。

客户端实现

go 复制代码
import (pb "grpc-demo/proto")

func main() {
	// 连接服务端
	conn, _ := grpc.Dial(
		"localhost:50051",
		grpc.WithTransportCredentials(insecure.NewCredentials()),
	)
	defer conn.Close()

	// 创建客户端
	client := pb.NewUserServiceClient(conn)

	// 调用 RPC 方法
	ctx := context.Background() // 空根上下文
	resp, _ := client.GetUser(ctx, &pb.GetUserRequest{UserId: 1})

	fmt.Printf("获取用户:%+v\n", resp.User)
}
  • client.Yyy(ctx, &Req{}):调用 RPC 方法

拦截器

拦截器类似 Gin 中间件,用于处理通用逻辑(日志、认证、限流)。

go 复制代码
// 日志拦截器
func LogInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
	// 请求前逻辑
	fmt.Printf("收到请求:%s\n", info.FullMethod)
	
	// 调用实际 RPC 方法
	resp, err := handler(ctx, req)
	
	// 请求后逻辑
	return resp, err
}

// 注册拦截器
func main() {
	lis, _ := net.Listen("tcp", ":50051")
	// 创建服务器时注册拦截器
	s := grpc.NewServer(grpc.UnaryInterceptor(LogInterceptor))
	pb.RegisterUserServiceServer(s, &UserServer{})
	s.Serve(lis)
}
  • grpc.NewServer(grpc.UnaryInterceptor(...)):创建 gRPC 服务器并注册拦截器
相关推荐
小陈工2 小时前
Python Web开发入门(十六):前后端分离架构设计——从“各自为政”到“高效协同”
开发语言·前端·数据库·人工智能·python
前进的李工2 小时前
MySQL用户管理与权限控制指南(含底层架构说明)
开发语言·数据库·sql·mysql·架构
少司府2 小时前
C++基础入门:类和对象(中)
c语言·开发语言·c++·类和对象·运算符重载·默认成员函数
橘子编程2 小时前
操作系统原理:从入门到精通全解析
java·linux·开发语言·windows·计算机网络·面试
唔662 小时前
原生 Android(Kotlin)仅串口「继承架构」完整案例二
android·开发语言·kotlin
错把套路当深情2 小时前
Kotlin 全方向开发技术栈指南
开发语言·kotlin
飞Link2 小时前
LangGraph 核心架构解析:节点 (Nodes) 与边 (Edges) 的工作机制及实战指南
java·开发语言·python·算法·架构
大神的风范3 小时前
QT部署YOLO11实时检测
驱动开发·深度学习·qt·目标检测·计算机视觉
cpp_learner3 小时前
Linux ARM架构 使用 linuxdeployqt 打包QT程序
qt
武藤一雄3 小时前
WPF中ViewModel之间的5种通讯方式
开发语言·前端·microsoft·c#·wpf