golang:使用 buf 替代 protoc 自动生成 protobuf

简介

buf 可以做 protoc 的替代品

  • buf 效率比 protoc 更好
  • buf 使用 yaml 文件,使用更清晰

NOTE:

  • 目前不支持 Windows,下面为 linux 演示
  • 官方文档:https://docs.buf.build/
  • 官方的BSR地址是https://buf.build/,我们可以https://buf.build/login页面进行注册登录。使用体验类似github

buf.build

buf之于proto,类似go mod之于golang

Buf 需要三个不同的文件来生成存根和反向代理:buf.work.yaml、buf.gen.yaml、buf.yaml。

另外,还有一个buf.lock文件,但是它不需要进行人工配置,它是由buf mod update命令所生成。这跟前端的npm、yarn等的lock文件差不多,golang的go.sum也差不多。

它的配置文件不多,也不复杂,维护起来非常方便,支持远程proto插件,支持远程第三方proto。对构建系统Bazel支持很好,对CI/CD系统也支持得很好。它还有很多优秀的特性。

buf.work.yaml

它一般放在项目的根目录下面,它代表的是一个工作区,通常一个项目也就一个该配置文件。

该配置文件最重要的就是directories配置项,列出了要包含在工作区中的模块的目录。目录路径必须相对于buf.work.yaml,像…/external就是一个无效的配置。

version: v1
directories:
  - api
  - third_party

buf.gen.yaml

它一般放在buf.work.yaml的同级目录下面,它主要是定义一些protoc生成的规则和插件配置。

# 配置protoc生成规则
version: v1
managed:
  enabled: false
plugins:
  # generate go struct code
  - name: go
    out: gen/api/go
    opt: paths=source_relative
  # generate grpc service code
  - name: go-grpc
    out: gen/api/go
    opt:
      - paths=source_relative
  # generate rest service code
  - name: go-http
    out: gen/api/go
    opt:
      - paths=source_relative
  # generate kratos errors code
  - name: go-errors
    out: gen/api/go
    opt:
      - paths=source_relative
  # generate message validator code
  - name: validate
    out: gen/api/go
    opt:
      - paths=source_relative
      - lang=go

buf.yaml

它放置的路径,你可以视之为protoc的–proto-path参数指向的路径,也就是proto文件里面import的相对路径。

需要注意的是,buf.work.yaml的同级目录必须要放一个该配置文件。

该配置文件的内容通常来说都是下面这个配置,不需要做任何修改,需要修改的情况不多。

version: v1
deps:
breaking:
  use:
    - FILE
lint:
  use:
    - DEFAULT

快速开始

安装

官方提供 3 种安装方式

bin
tar package
go/bin

第一种:

brew install bufbuild/buf/buf

第二种:

go install github.com/bufbuild/buf/cmd/buf@v1.15.1

第三种:

BIN="/usr/local/bin" && \
VERSION="0.43.2" && \
BINARY_NAME="buf" && \
  curl -sSL \
    "https://github.com/bufbuild/buf/releases/download/v${VERSION}/${BINARY_NAME}-$(uname -s)-$(uname -m)" \
    -o "${BIN}/${BINARY_NAME}" && \
  chmod +x "${BIN}/${BINARY_NAME}"

检查是否安装成功

buf --version
1.15.1

示例

初始化项目

创建一个文件,然后在文件夹下执行:

$ mkdir buf_test && cd buf_test
$ go mod init grpc-gateway-demo
go: creating new go.mod: module grpc-gateway-demo
$ ls
go.mod
$ touch main.go

目前项目目录如下:

.
├── go.mod
├── main.go
└── proto

proto目录是所有proto文件的目录

创建buf.work.yaml

cd buf_test
touch buf.work.yaml

此文件指定工作空间中包含 Protocol Buffer 定义的所有文件夹/目录。内容:

version: v1
directories:
  - proto

创建buf.gen.yaml

cd buf_test
touch buf.gen.yaml

这些文件指定编译器应该使用的所有插件和相关选项。

使用 Buf,你可以简单地在 YAML 文件中指定名称和选项。Buf 还允许构建代码使用远程插件(即,指定的插件将在构建过程中由 Buf 自动下载并由本地系统上的 Buf 维护)。内容为:

version: v1
plugins:
  # generate go structs for protocol buffer defination
  - remote: buf.build/library/plugins/go:v1.27.1-1
    out: gen/go
    opt:
      - paths=source_relative
  # generate gRPC stubs in golang
  - remote: buf.build/library/plugins/go-grpc:v1.1.0-2
    out: gen/go
    opt:
      - paths=source_relative
  # generate reverse proxy from protocol definations
  - remote: buf.build/grpc-ecosystem/plugins/grpc-gateway:v2.6.0-1
    out: gen/go
    opt:
      - paths=source_relative
  # generate openapi documentation for api
  - remote: buf.build/grpc-ecosystem/plugins/openapiv2:v2.6.0-1
    out: gen/openapiv2

创建buf.yaml

  • 该文件应位于所有 proto 文件的根目录中。
  • 目的:
    • 为proto指定编译 proto 文件(例如 Google API)所需的依赖项。
    • 为这个 pb 目录创建一个 buf 的模块。此后便可以使用 buf 的各种命令来管理这个 buf 模块了
cd buf_test/proto
 buf mod init

此时会在根目录多出一个buf.yaml文件,内容为

version: v1
breaking:
  use:
    - FILE
lint:
  use:
    - DEFAULT

修改:

version: v1
deps:
- buf.build/googleapis/googleapis
lint:
use:
  - DEFAULT
breaking:
use:
  - FILE

生成

此时项目目录:

├── buf.gen.yaml
├── buf.work.yaml
├── go.mod
├── main.go
└── proto
    ├── buf.yaml

在项目根目录中你可以通过运行 buf build 命令来测试你的配置

$ cd buf_test
$ buf build
Failure: directory "proto" listed in buf.work.yaml contains no .proto files

我们来添加一个proto文件:proto/hello/hello_world.proto :

// define syntax used in proto file
syntax = "proto3";
// options used by gRPC golang plugin(not related to gRPC gateway)
option go_package = "helloword/grpc-gateway-demo;grpc_gateway_demo";

// well know type by google, gRPC gateway uses HTTP annotation.

package hello_world;

// simple message
message HelloRequest { string name = 1; }

message HelloReply { string message = 1; }

// a gRPC service
service Greeter {
  // SayHello is a rpc call and a option is defined for it
  rpc SayHello(HelloRequest) returns (HelloReply) {}
}

重新执行:

$ buf build
$ buf generate
WARN    Plugin "buf.build/library/go" is deprecated
WARN    Plugin "buf.build/library/go-grpc" is deprecated
WARN    Plugin "buf.build/grpc-ecosystem/grpc-gateway" is deprecated
WARN    Plugin "buf.build/grpc-ecosystem/openapiv2" is deprecated

最后:

$ tree
.
├── buf.gen.yaml
├── buf.work.yaml
├── gen
│   ├── go
│   │   └── hello
│   │       ├── hello_world_grpc.pb.go
│   │       └── hello_world.pb.go
│   └── openapiv2
│       └── hello
│           └── hello_world.swagger.json
├── go.mod
├── main.go
└── proto
    ├── buf.yaml
    └── hello
        └── hello_world.proto

https://www.cuiwei.net/p/1679512807#/
https://blog.xuegaogg.com/posts/1951/

https://www.cnblogs.com/rongfengliang/p/16703778.html

http://www.guoxiaolong.cn/blog/?id=11287

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值