欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 【gRPC】Go语言下的gRPC

【gRPC】Go语言下的gRPC

2025/11/19 16:59:33 来源:https://blog.csdn.net/2301_77868664/article/details/143559151  浏览:    关键词:【gRPC】Go语言下的gRPC

一、RPC有四种需求:

1.1 简单模式

       这种模式最为传统,即客户端发起一次请求,服务端响应一个数据,这个大家平时熟悉的RPC没有大的区别,所以不再详细介绍。

1.2 服务端数据流模式

       这种模式是客户端发起一次请求,服务端返回一段连续的数据流。典型的例子是客户端向服务端发送一个股票代码,服务端就把该股票的实时数据源源不断的返回给客户端。

1.3 客户端数据流模式

       与服务端数据流模式相反,这次是客户端源源不断的向服务端发送数据流,而在发送结束后,由服务端返回一个响应。典型的例子就是物联网终端向服务器报发数据。

1.4 双向数据流模式

       顾名思义,这是客户端和服务端都可以向对方发送数据流,这个时候双方的数据可以同时互相发送,也就是可以实现实时交互。典型的例子就是聊天机器人。

二、四种需求的代码如下:

2.1 简单模式

2.1.1 proto 文件

syntax = "proto3";package helloworld;// 指定 Go 包的路径
option go_package = ".;proto";// 这是一个rpc服务
service Hello {rpc Hello(HelloRequest) returns (HelloResponse);
}message HelloRequest {string name = 1; // 1 是编号
}message HelloResponse {string reply = 1;
}

       我们在编译 proto 文件的时候,我们需要先将安装了最新版本的 protoc-gen-goprotoc-gen-go-grpc 插件。如果你还没有安装或需要更新它们,可以使用以下命令:

# 安装最新的 protoc-gen-go 插件
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest# 安装最新的 protoc-gen-go-grpc 插件
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

       我们需要生成普通Go代码的时候,使用 protoc 命令时,命令格式如下,我们会根据 helloworld.proto 文件生成普通的 Go 代码文件。

protoc -I . helloworld.proto --go_out=.

       我们需要生成gRPC代码的时候,使用 protoc 命令时,命令格式如下,我们会使用 --go-grpc_out 来生成 gRPC 相关的代码(包括客户端和服务端的 gRPC 代码):

protoc -I . helloworld.proto --go-grpc_out=.

       我们可以使用完整的命令行,来一次性生成所有的代码(普通的 Go 代码和 gRPC 相关的代码),你可以将两个命令合并成一个:

protoc -I . helloworld.proto --go_out=. --go-grpc_out=.

2.1.2 server端

package mainimport ("context""fmt""google.golang.org/grpc""log""net"pb "xuego/protobuf/helloworld/proto"
)type Server struct {pb.UnimplementedHelloServer // 继承自动生成的 Unimplemented 方法,可以确保将来不破坏接口兼容性
}// SayHello 实现了 Greeter 服务的 SayHello 方法
func (s *Server) Hello(ctx context.Context, request *pb.HelloRequest) (*pb.HelloResponse, error) {// 构造并返回响应return &pb.HelloResponse{Reply: "Hello " + request.Name,}, nil
}func main() {// 创建一个新的 gRPC 服务器g := grpc.NewServer()// 注册 Greeter 服务到 gRPC 服务器pb.RegisterHelloServer(g, &Server{})// 定义服务器监听地址和端口listen, err := net.Listen("tcp", ":8080")if err != nil {log.Fatalf("failed to listen: %v", err)}// 输出日志,表明服务器开始监听fmt.Println("Server is listening on port :50051")// 启动 gRPC 服务器if err := g.Serve(listen); err != nil {log.Fatalf("failed to serve: %v", err)}
}

2.1.3 client端

package mainimport ("context""fmt""google.golang.org/grpc""xuego/protobuf/helloworld/proto"
)func main() {conn, err := grpc.Dial("localhost:8080", grpc.WithInsecure())if err != nil {panic(err)}defer conn.Close()c := proto.NewHelloClient(conn)r, err := c.Hello(context.Background(), &proto.HelloRequest{Name: "xuego"})if err != nil {panic(err)}fmt.Errorf(r.Reply)
}

2.2 服务端数据流模式

&& 客户端数据流模式

&& 双向数据流模式

2.2.1 proto 文件

syntax = "proto3";option go_package = ".;proto";service Greeter {rpc GetStream(StreamReqData) returns (stream StreamResData); // 服务端流模式rpc PutStream(stream StreamReqData) returns (StreamResData); // 客户端流模式rpc AllStream(stream StreamReqData) returns (stream StreamResData); // 双向流模式
}message StreamReqData {string data = 1;
}message StreamResData {string data = 1;
}

在这些模式下,他们在服务端中写的函数的参数与简单模式的不同,需要注意一下!!!!

2.2.2 server端

package mainimport ("fmt""google.golang.org/grpc""net""sync""time"pb "xuego/stream_grpc_test/proto"
)const PORT = ":50052"type Server struct {pb.UnimplementedGreeterServer
}func (s *Server) GetStream(req *pb.StreamReqData, res pb.Greeter_GetStreamServer) error {i := 0for {i++_ = res.Send(&pb.StreamResData{Data: fmt.Sprintf("%v", time.Now().Unix()),})time.Sleep(time.Second)if i > 10 {break}}return nil
}func (s *Server) PutStream(cliStr pb.Greeter_PutStreamServer) error {for {if a, err := cliStr.Recv(); err != nil {fmt.Println(err)break} else {fmt.Println(a.Data)}}return nil
}func (s *Server) AllStream(allStr pb.Greeter_AllStreamServer) error {wg := sync.WaitGroup{}wg.Add(2)go func() {defer wg.Done()for {data, _ := allStr.Recv()fmt.Println("收到客户端下消息:" + data.Data)}}()go func() {defer wg.Done()for {_ = allStr.Send(&pb.StreamResData{Data: "我是服务器"})time.Sleep(time.Second)}}()wg.Wait()return nil
}func main() {lis, err := net.Listen("tcp", PORT)if err != nil {panic(err)}s := grpc.NewServer()pb.RegisterGreeterServer(s, &Server{})err = s.Serve(lis)if err != nil {panic(err)}
}

2.2.3 client端

package mainimport ("context""fmt""google.golang.org/grpc""sync""time"pb "xuego/stream_grpc_test/proto"
)func main() {conn, err := grpc.Dial("localhost:50052", grpc.WithInsecure())if err != nil {panic(err)}defer conn.Close()// 服务端流模式c := pb.NewGreeterClient(conn)res, _ := c.GetStream(context.Background(), &pb.StreamReqData{Data: "陌客网"})for {a, err := res.Recv()if err != nil {fmt.Println(err)break}fmt.Println(a.Data)}// 客户端流模式putS, _ := c.PutStream(context.Background())i := 0for {i++putS.Send(&pb.StreamReqData{Data: fmt.Sprintf("慕课网%d", i),})time.Sleep(time.Second)if i > 10 {break}}// 双向流模式allStr, _ := c.AllStream(context.Background())wg := sync.WaitGroup{}wg.Add(2)go func() {defer wg.Done()for {data, _ := allStr.Recv()fmt.Println("收到客户端下消息:" + data.Data)}}()go func() {defer wg.Done()for {_ = allStr.Send(&pb.StreamReqData{Data: "我是客户段"})time.Sleep(time.Second)}}()wg.Wait()
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词