Go 语言 gRPC 服务——四种通信模式

知识库
知识库文档
/tech-stacks/grpc/examples/Go 语言 gRPC 服务——四种通信模式.md

文档

gRPC 例程:Go 语言四种通信模式

目标

用 Go 实现 gRPC 的四种通信模式:Unary、Server Streaming、Client Streaming、Bidirectional Streaming。

Proto 定义

syntax = "proto3";
package calculator;
option go_package = "example.com/grpc-demo/calculator";

service Calculator {
  // 一元调用
  rpc Add(AddRequest) returns (AddResponse);

  // 服务端流:客户端发一次,服务端发多次
  rpc Fibonacci(FibRequest) returns (stream FibResponse);

  // 客户端流:客户端发多次,服务端发一次
  rpc Average(stream AvgRequest) returns (AvgResponse);

  // 双向流:双方自由发送
  rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}

message AddRequest  { int32 a = 1; int32 b = 2; }
message AddResponse { int32 result = 1; }

message FibRequest  { int32 n = 1; }
message FibResponse { int64 value = 1; }

message AvgRequest  { int32 num = 1; }
message AvgResponse { double average = 1; }

message ChatMessage { string user = 1; string text = 2; }

服务端实现

package main

import (
	"context"
	"io"
	"log"
	"net"

	pb "example.com/grpc-demo/calculator"
	"google.golang.org/grpc"
)

type server struct {
	pb.UnimplementedCalculatorServer
}

// Unary
func (s *server) Add(ctx context.Context, req *pb.AddRequest) (*pb.AddResponse, error) {
	return &pb.AddResponse{Result: req.A + req.B}, nil
}

// Server Streaming
func (s *server) Fibonacci(req *pb.FibRequest, stream pb.Calculator_FibonacciServer) error {
	var a, b int64 = 0, 1
	for i := int32(0); i < req.N; i++ {
		stream.Send(&pb.FibResponse{Value: a})
		a, b = b, a+b
	}
	return nil
}

// Client Streaming
func (s *server) Average(stream pb.Calculator_AverageServer) error {
	var sum, count int32
	for {
		req, err := stream.Recv()
		if err == io.EOF {
			return stream.SendAndClose(&pb.AvgResponse{
				Average: float64(sum) / float64(count),
			})
		}
		if err != nil { return err }
		sum += req.Num
		count++
	}
}

// Bidirectional Streaming
func (s *server) Chat(stream pb.Calculator_ChatServer) error {
	for {
		msg, err := stream.Recv()
		if err == io.EOF { return nil }
		if err != nil { return err }
		log.Printf("[%s]: %s", msg.User, msg.Text)
		stream.Send(&pb.ChatMessage{
			User: "Server",
			Text: "收到: " + msg.Text,
		})
	}
}

func main() {
	lis, _ := net.Listen("tcp", ":50051")
	s := grpc.NewServer()
	pb.RegisterCalculatorServer(s, &server{})
	log.Println("gRPC 服务启动在 :50051")
	s.Serve(lis)
}

运行步骤

# 生成代码
protoc --go_out=. --go-grpc_out=. calculator.proto

# 启动服务端
go run server/main.go

# 启动客户端测试(需编写 client.go)
go run client/main.go

运行结果示例

2024/01/01 gRPC 服务启动在 :50051
[Alice]: Hello!
[Bob]: Hi there!

四种模式对比

模式 客户端 服务端 典型场景
Unary 1 请求 → 1 响应 1 请求 → 1 响应 简单查询
Server Stream 1 请求 → 流式接收 1 请求 → 流式发送 日志订阅
Client Stream 流式发送 → 1 响应 流式接收 → 1 响应 文件上传
Bidi Stream 自由收发 自由收发 聊天、实时协作

信息

路径
/tech-stacks/grpc/examples/Go 语言 gRPC 服务——四种通信模式.md
更新时间
2026/5/31