0

0

如何使用Golang实现gRPC通信_gRPC通信实现步骤说明

P粉602998670

P粉602998670

发布时间:2026-01-14 10:50:37

|

124人浏览过

|

来源于php中文网

原创

Protocol Buffer 接口必须在 .proto 文件中正确定义,包括 syntax、package、service 和 message;需用 protoc-gen-go 与 protoc-gen-go-grpc 插件生成代码;Server 必须调用 RegisterXXXServer 并监听;Client 需复用连接并设置 context 超时。

如何使用golang实现grpc通信_grpc通信实现步骤说明

定义 Protocol Buffer 接口(.proto 文件)

gRPC 的核心是接口定义必须先写在 .proto 文件里,Go 代码只是生成结果。不写对这个文件,后续所有步骤都会失败。

常见错误:直接写 Go 结构体当服务接口、漏写 syntax = "proto3";、在 service 中用 rpc 声明方法但没配对的 message 请求/响应类型。

  • 必须声明 package,它会映射为 Go 的包名(如 package helloworld; → 生成代码在 helloworld 目录)
  • 服务方法参数和返回值必须是 message 类型,不能是基础类型(如 stringint32 单独作参数)
  • 若需流式通信,用 stream 关键字,例如 rpc SayHelloStream(stream HelloRequest) returns (stream HelloReply);
syntax = "proto3";

package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

用 protoc 生成 Go 代码

Go 不自带 protoc 插件,必须手动安装 protoc-gen-goprotoc-gen-go-grpc,否则 protoc 会报错“Plugin failed with status code 1”。

生成命令容易漏掉 --go-grpc_out —— 只用 --go_out 只生成数据结构,不生成 gRPC Server/Client 接口,运行时会提示 undefined: helloworld.NewGreeterClient 这类错误。

立即学习go语言免费学习笔记(深入)”;

MewXAI
MewXAI

一站式AI绘画平台,支持AI视频、AI头像、AI壁纸、AI艺术字、可控AI绘画等功能

下载
  • 安装插件:go install google.golang.org/protobuf/cmd/protoc-gen-go@latestgo install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
  • 执行生成(确保当前目录有 helloworld.proto):
    protoc --go_out=. --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld.proto
  • 生成后会得到两个文件:helloworld/helloworld.pb.go(消息结构)和 helloworld/helloworld_grpc.pb.go(客户端接口、服务端抽象接口)

实现 gRPC Server(基于 net.Listener)

Server 启动依赖 net.Listen + grpc.NewServer() + RegisterXXXServer 三步缺一不可。最容易忽略的是没调用 RegisterXXXServer,导致客户端调用时返回 UNIMPLEMENTED 错误。

另一个坑是未处理监听地址冲突(如端口被占),net.Listen 失败后没检查 error,程序静默 panic 或卡住。

  • grpc.NewServer() 可传入选项,例如启用 TLS:grpc.Creds(credentials.NewTLS(...))
  • 注册服务必须用生成的 RegisterGreeterServer 函数,不是手写的结构体指针直传
  • 启动后需阻塞等待连接,常用 fmt.Scanln()signal.Notify 捕获中断
package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    pb "your-module/helloworld"
)

type server struct {
    pb.UnimplementedGreeterServer
}

func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello " + req.Name}, nil
}

func main() {
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    log.Println("gRPC server listening on :50051")
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

编写 gRPC Client 并处理连接生命周期

Client 端最常出问题的是连接没关闭、没设超时、或复用已关闭的 *grpc.ClientConn。一旦连接断开又继续调用,会报 rpc error: code = Unavailable desc = closing transport due to: connection error

不要把 grpc.Dial 写在每次 RPC 调用前——它开销大且可能泄漏连接;也不要在 defer 中无条件 Close(),因为连接通常要复用。

  • 推荐用 grpc.WithTransportCredentials(insecure.NewCredentials()) 开发时跳过 TLS(生产环境必须配证书)
  • 务必设置上下文超时:ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second),再传给 RPC 方法
  • 连接应作为长生命周期对象管理(如封装进 struct),避免频繁 Dial/Close
package main

import (
    "context"
    "log"
    "time"

    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    pb "your-module/helloworld"
)

func main() {
    conn, err := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()

    client := pb.NewGreeterClient(conn)
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()

    r, err := client.SayHello(ctx, &pb.HelloRequest{Name: "World"})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.GetMessage())
}
实际跑通的关键不在语法多炫,而在 .proto 定义是否闭环、protoc 插件是否齐全、Server 是否完成 Register、Client 是否正确携带 context 超时——这四点任一缺失,都会让请求卡在无声的失败里。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

178

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

226

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

337

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

208

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

388

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

195

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

189

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

192

2025.06.17

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

0

2026.01.14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.7万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号