3. Go语言gRPC环境搭建:模块初始化、protoc编译器与插件配置

搭建gRPC开发环境是进入微服务通信优化的第一步。本章将引导你完成Go模块初始化、protoc编译器安装、protoc-gen-go插件配置,并运行第一个gRPC服务端与客户端。环境就绪后,后续章节的并发建模与性能优化才能落地。

3.1 环境全景:工具链与依赖关系

gRPC-Go开发依赖三个核心层次:协议编译器(protoc)、Go代码生成插件、gRPC运行时库。下图展示了各组件之间的协作关系。

gRPC-Go 开发环境组件关系 用户 .proto 文件 protoc 编译器 protoc-gen-go protoc-gen-go-grpc *.pb.go *_grpc.pb.go 说明:protoc 读取 .proto 文件,调用两个插件分别生成消息类型代码和服务桩代码

3.2 Go模块初始化

从Go 1.16开始,go mod是官方推荐的依赖管理方式。gRPC-Go项目必须使用Go Modules管理依赖版本。

操作步骤:

  1. 创建项目目录并进入
  2. 执行 go mod init 初始化模块
  3. 后续通过 go get 拉取gRPC依赖
mkdir grpc-demo && cd grpc-demo
go mod init github.com/yourname/grpc-demo

模块名建议使用完整的仓库路径,避免与标准库冲突。初始化后目录下会生成 go.mod 文件。

3.3 protoc编译器安装

protoc是Protocol Buffers的官方编译器,负责将 .proto 文件编译成目标语言代码。不同操作系统安装方式如下:

操作系统 安装方式 验证命令
macOS brew install protobuf protoc --version
Ubuntu/Debian apt install protobuf-compiler protoc --version
Windows 从GitHub Releases下载预编译包,加入PATH protoc --version
手动安装 从 protobuf releases 下载对应平台压缩包 解压后将 bin/protoc 加入PATH

版本建议:推荐使用 protoc 3.21.x 或更高版本。低版本可能不支持最新的proto3语法特性,如 optional 关键字。

3.4 protoc-gen-go与protoc-gen-go-grpc插件配置

protoc本身不生成Go代码,需要安装两个专用插件:

  • protoc-gen-go:生成消息类型的Go结构体(*.pb.go)
  • protoc-gen-go-grpc:生成gRPC服务端和客户端桩代码(*_grpc.pb.go)

使用 go install 安装到 $GOPATH/bin:

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

安装后确认插件在PATH中:

which protoc-gen-go
which protoc-gen-go-grpc

常见错误:如果 protoc 找不到插件,会报错 protoc-gen-go: program not found or is not executable。请确保 $GOPATH/bin 已加入系统PATH环境变量。

3.5 编写第一个proto文件

在项目根目录创建 proto/hello.proto:

syntax = "proto3";

package hello;

option go_package = "github.com/yourname/grpc-demo/proto/hello";

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

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

关键字段说明:

  • syntax = "proto3":使用proto3语法
  • option go_package:指定生成的Go包路径,必须与模块路径对应
  • service Greeter:定义一个gRPC服务,包含一个RPC方法

3.6 编译proto文件生成Go代码

在项目根目录执行编译命令:

protoc --go_out=. --go-grpc_out=. proto/hello.proto

执行后生成两个文件:

  • proto/hello/hello.pb.go — 消息类型代码
  • proto/hello/hello_grpc.pb.go — 服务端/客户端桩代码

生成的目录结构如下:

grpc-demo/
├── go.mod
├── go.sum
├── proto/
│   ├── hello.proto
│   └── hello/
│       ├── hello.pb.go
│       └── hello_grpc.pb.go

3.7 第一个gRPC服务端

创建 server/main.go:

package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    pb "github.com/yourname/grpc-demo/proto/hello"
)

type server struct {
    pb.UnimplementedGreeterServer
}

func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
    log.Printf("收到请求: %v", req.GetName())
    return &pb.HelloReply{Message: "Hello, " + req.GetName()}, nil
}

func main() {
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("监听失败: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    log.Println("gRPC服务端启动于 :50051")
    if err := s.Serve(lis); err != nil {
        log.Fatalf("服务失败: %v", err)
    }
}

3.8 第一个gRPC客户端

创建 client/main.go:

package main

import (
    "context"
    "log"
    "time"

    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    pb "github.com/yourname/grpc-demo/proto/hello"
)

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

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

    resp, err := client.SayHello(ctx, &pb.HelloRequest{Name: "gRPC"})
    if err != nil {
        log.Fatalf("调用失败: %v", err)
    }
    log.Printf("收到响应: %v", resp.GetMessage())
}

3.9 运行验证

启动服务端和客户端,验证通信是否正常:

# 终端1:启动服务端
go run server/main.go
# 输出: gRPC服务端启动于 :50051

# 终端2:运行客户端
go run client/main.go
# 输出: 收到响应: Hello, gRPC

验证要点:

  • 服务端日志显示 收到请求: gRPC
  • 客户端日志显示 收到响应: Hello, gRPC
  • 两端无panic或连接拒绝错误

3.10 环境搭建检查清单

检查项 验证方式 预期结果
Go版本 go version ≥ 1.18
protoc版本 protoc --version ≥ 3.21.0
protoc-gen-go which protoc-gen-go 路径存在
protoc-gen-go-grpc which protoc-gen-go-grpc 路径存在
gRPC依赖 go list -m google.golang.org/grpc 版本 ≥ 1.50.0
服务端启动 go run server/main.go 无报错,监听 :50051
客户端调用 go run client/main.go 收到正确响应