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 服务器并注册拦截器
相关推荐
eastyuxiao7 小时前
OpenClaw 自动处理核心逻辑
开发语言·人工智能
小郑加油7 小时前
python学习Day10天:列表进阶 + 内置函数 + 代码简化
开发语言·python·学习
eastyuxiao7 小时前
影响 OpenClaw 自动处理效率的核心因素
开发语言·人工智能
啧不应该啊7 小时前
Day1 python与c宏观区别
c语言·开发语言
时空系7 小时前
第13篇:综合实战——制作我的小游戏 python中文编程
开发语言·python·ai编程
XiYang-DING7 小时前
【Java EE】CAS(Compare And Swap)
java·开发语言·java-ee
OneT1me7 小时前
CVE-2026-31431 的C语言版本
c语言·开发语言·安全威胁分析
xun-ming8 小时前
AI时代Java程序员自救手册
java·开发语言·人工智能
张健11564096488 小时前
C++访问控制与友元
java·开发语言·c++
2zcode8 小时前
基于MATLAB改进最大熵法的大规模新能源并网概率潮流计算
开发语言·matlab