Golang中如何在不同仓库间共享.proto文件

Golang中如何在不同仓库间共享.proto文件 假设有两个服务位于不同的代码仓库中(客户端和服务器端)。它们通过 gRPC 进行通信,因此需要编译 .proto 文件以生成相应的存根。

问题是如何在这些服务之间共享这些文件?

我想为 proto 模式创建第三个仓库。我了解到的方法是:将更改推送到该仓库,然后通过 CI/CD 自动生成存根,将其打包(使用 Maven?)并上传到某种注册中心(例如 GitHub Packages)。接着,将其作为包下载(在 Java 中使用 pom.xml),并包含在项目中。

在这样的配置过程中,我遇到了一些问题。 你能给我一些建议、想法或不同的方法吗?


更多关于Golang中如何在不同仓库间共享.proto文件的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

另一种解决方案是将 proto-schemas 仓库作为 Git 子模块添加到两个服务的仓库中。你必须在两个构建中都生成存根,但这消除了上传它们到注册中心的需求。

更多关于Golang中如何在不同仓库间共享.proto文件的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在阅读不同的选项时,我觉得子模块是一个可行的选择,但并非最佳,也不够灵活——无论如何,我会研究一下,谢谢。

让我再问第二个问题。我想在Kubernetes中开发一个应用,使用像Skaffold或Tilt-dev(<-- 更倾向于后者)这样的工具。这些工具有助于将服务自动部署到本地集群中,但如何托管数据库呢?我有docker-compose文件也可以运行它们,但在本地开发期间,我应该将它们放在集群外部还是内部?是否有可能在集群重启期间保持状态和数据?

谢谢。

在Go中跨仓库共享.proto文件的常见做法是使用独立的proto仓库配合Go Modules。以下是具体实现方案:

方案一:独立的proto仓库 + Go Modules

1. 创建独立的proto仓库

// 仓库:github.com/yourorg/protos
// user.proto
syntax = "proto3";

package yourorg.common.v1;

option go_package = "github.com/yourorg/protos/gen/go/yourorg/common/v1";

message User {
  string id = 1;
  string name = 2;
  string email = 3;
}

2. 配置go.mod

// 在proto仓库中
module github.com/yourorg/protos

go 1.21

require google.golang.org/protobuf v1.32.0

3. 添加Makefile生成代码

# Makefile in proto repository
PROTO_DIR=.
GO_OUT_DIR=gen/go

.PHONY: gen
gen:
    mkdir -p $(GO_OUT_DIR)
    protoc --proto_path=$(PROTO_DIR) \
           --go_out=$(GO_OUT_DIR) \
           --go_opt=paths=source_relative \
           $(PROTO_DIR)/**/*.proto

4. 在服务中引用

// 客户端服务go.mod
module github.com/yourorg/client

go 1.21

require github.com/yourorg/protos v1.0.0

replace github.com/yourorg/protos => ../protos // 本地开发时使用
// 客户端代码示例
package main

import (
    "context"
    "log"

    pb "github.com/yourorg/protos/gen/go/yourorg/common/v1"
    "google.golang.org/grpc"
)

func main() {
    conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()
    
    client := pb.NewUserServiceClient(conn)
    // 使用生成的客户端代码
}

方案二:使用buf工具链

1. 安装和配置buf

# buf.yaml (在proto仓库根目录)
version: v1
lint:
  use:
    - STANDARD
breaking:
  use:
    - FILE

2. 配置buf.gen.yaml

# buf.gen.yaml
version: v1
plugins:
  - name: go
    out: gen/go
    opt: paths=source_relative
  - name: go-grpc
    out: gen/go
    opt: paths=source_relative

3. 使用buf push到BSR

# 推送proto到Buf Schema Registry
buf push https://buf.build/yourorg/protos

4. 在其他服务中引用

// 通过go.mod引用BSR生成的代码
require buf.build/gen/go/yourorg/protos/protocolbuffers/go v1.32.0

方案三:Git Submodule方式

1. 添加submodule

# 在服务仓库中添加proto仓库作为submodule
git submodule add https://github.com/yourorg/protos protos
git submodule update --init --recursive

2. 本地生成代码脚本

// generate.go
package main

import (
    "os"
    "os/exec"
    "path/filepath"
)

func main() {
    protoDir := "./protos"
    outputDir := "./gen"
    
    cmd := exec.Command("protoc",
        "--proto_path="+protoDir,
        "--go_out="+outputDir,
        "--go_opt=paths=source_relative",
        "--go-grpc_out="+outputDir,
        "--go-grpc_opt=paths=source_relative",
        filepath.Join(protoDir, "**/*.proto"),
    )
    
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.Run()
}

方案四:容器化构建

1. Dockerfile for proto generation

FROM golang:1.21-alpine AS builder

RUN apk add --no-cache protobuf protobuf-dev
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

WORKDIR /src
COPY . .
RUN mkdir -p gen && \
    protoc --proto_path=. \
           --go_out=gen \
           --go_opt=paths=source_relative \
           --go-grpc_out=gen \
           --go-grpc_opt=paths=source_relative \
           **/*.proto

2. CI/CD Pipeline示例

# .github/workflows/proto-release.yaml
name: Proto Release
on:
  push:
    tags:
      - 'v*'

jobs:
  generate-and-push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Generate Go code
        uses: bufbuild/buf-setup-action@v1
        with:
          version: latest
      
      - name: Generate
        run: buf generate
      
      - name: Push to registry
        run: |
          git config user.name "GitHub Actions"
          git config user.email "actions@github.com"
          git add gen/
          git commit -m "Generated code for ${GITHUB_REF}"
          git push

版本管理建议

使用语义化版本控制proto变更:

// go.mod中使用版本约束
require github.com/yourorg/protos v1.2.0

// 或者使用commit hash
require github.com/yourorg/protos v0.0.0-20240101120000-abcdef123456

这些方案中,方案一(独立仓库+Go Modules)在Go生态中最常用,方案二(buf工具链)提供了更完整的proto管理能力。选择哪种方案取决于团队规模和项目复杂度。

回到顶部