grpc-api模块化依赖

目标

将 gRPC 的 .proto、.pb.go、_grpc.pb.go 统一保存在 底层仓库的 api/ 目录 下,同时让上层 服务直接依赖该 api 模块。

目录结构

go 复制代码
仓库名/
├── api/
│   ├── go.mod
│   ├── category/v1/
│   │   ├── category.proto
│   │   ├── category.pb.go
│   │   └── category_grpc.pb.go
│   ├── invoice/v1/
│   │   ├── invoice.proto
│   │   ├── invoice.pb.go
│   │   └── invoice_grpc.pb.go
│   └── operation/v1/
│       ├── homepage_recommendation.proto
│       ├── homepage_recommendation.pb.go
│       └── homepage_recommendation_grpc.pb.go
├── cmd/
├── configs/
├── internal/
└── third_party/

操作

1.在 api/ 目录下新增独立 go.mod 文件

文件:api/go.mod

go 复制代码
module ****.git(仓库git地址)/api

go 1.25.0

require (
	google.golang.org/grpc v1.80.0
	google.golang.org/protobuf v1.36.11
)

require (
	golang.org/x/net v0.52.0 // indirect
	golang.org/x/sys v0.42.0 // indirect
	golang.org/x/text v0.35.0 // indirect
	google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect
)

注意:

●module 写 仓库路径 + /api

●不要写网页地址

●不要写 /tree/xxx

●不要把分支名写进 module path

2.为每个 proto 设置正确的 go_package

例子

api/category/v1/category.proto

go 复制代码
option go_package = "****.git(仓库git地址)/api/category/v1;v1";

proto全部内容

go 复制代码
syntax = "proto3";

package agent.v1;

option go_package = "****.git(仓库git地址)/api/agent/v1;v1";

import "google/protobuf/timestamp.proto";

service AgentService {
  rpc GetAgentInfoList(GetAgentInfoListReq) returns (GetAgentInfoListResp);
}

message GetAgentInfoListReq {
  repeated int32 idList = 1;
  string platformType = 2; // 客户端类型[pc/android/ios/harmony/h5]
}

message GetAgentInfoListResp {
  repeated AgentInfo agentInfoList = 1;
}

message AgentInfo {
  int64 id = 1;                                   // 主键id
  string name = 2;                                // 名称
  string description = 3;                         // 描述
  string iconUrl = 4;                            // 图标
  string category = 5;                            // 分类
  int32 status = 6;                               // 状态[0=删除 1=未删除]
  int32 convSource = 7;                          // 会话源
  string tag = 8;                                 // 标签数组[逗号分隔]
  string creator_id = 9;                          // 创建人id
  string lastUpdaterId = 10;                    // 最后更新人id
  google.protobuf.Timestamp createTime = 11;     // 创建时间
  google.protobuf.Timestamp lastUpdateTime = 12;// 更新时间
  string statusMsg = 13;                         // 状态消息
  int32 hot = 14;                                 // 热门
  int32 subStatus = 15;                          // 订阅状态 1=已订阅 2=未订阅
  int32 sortNum = 16;                            // 排序字段,越小越靠前
}

3.生成代码后提交到仓库

生成后的文件包括:

●*.pb.go

●*_grpc.pb.go

这些文件与 .proto 一起保存在 api/ 目录下,并正常提交 Git。

4 上层服务直接依赖 api 模块

在 上层项目中执行:

go 复制代码
go get ***.git(仓库git地址)/api@<tag或commit>
go 复制代码
import categoryv1 " ***.git(仓库git地址)/api/category/v1"
import invoicev1 " ***.git(仓库git地址)/api/invoice/v1"

如果嫌导入方式很长, 可以用 go.mod 的 replace 进行简化, 目前 esp-console 项目将其简写为 esp-grpc

●go.mod 文件:

go 复制代码
// module aira-aiplatform-esp-console
module aira-aiplatform-esp-console
go 1.25.0
require (
	esp-grpc v0.0.0
    // ...
)
// go get ***.git(仓库git地址)/api@commit-or-tag
replace esp-grpc => ***.git(仓库git地址)/api v0.0.0-20260409054836-7902fa4f81a0
require (
// indirect requires...
)

●go文件的 import:

go 复制代码
import (
	invoicev1 "esp-grpc/invoice/v1"
	operationv1 "esp-grpc/operation/v1"
    // ...
)

私有仓库配置
因为是私有仓库,需要在本地或 CI 配置:

go 复制代码
go env -w GOPRIVATE=codeup.aliyun.com(仓库域名)

作用:私有库不走代理、不校验 sum

并确保当前机器已经具备 Codeup 的 Git 拉取权限。

执行 go mod tidy

也可使用下面的shell脚本直接执行拉取底层被依赖项目的代码

powershell 复制代码
#!/usr/bin/env bash

set -euo pipefail

readonly TARGET_DEPENDENCY="esp-grpc"## 上层项目import 底层项目的简称
readonly REPLACEMENT_MODULE=" ***.git(仓库git地址)/api" ##被依赖的grpc仓库地址
readonly VERSION_TEMPLATE='{{.Version}}'

usage() {
  cat <<'EOF'
Usage:
  scripts/update_esp_grpc_replace.sh <commit-hash>

Example:
  scripts/update_esp_grpc_replace.sh e4251adf9639
EOF
}

main() {
  if [[ $# -ne 1 ]]; then
    usage
    exit 1
  fi

  local commit_hash="$1"
  local resolved_version

  resolved_version="$(go list -m -f "${VERSION_TEMPLATE}" "${REPLACEMENT_MODULE}@${commit_hash}")"

  if [[ -z "${resolved_version}" ]]; then
    echo "Failed to resolve version for commit: ${commit_hash}" >&2
    exit 1
  fi

  go mod edit -replace="${TARGET_DEPENDENCY}=${REPLACEMENT_MODULE}@${resolved_version}"
  go mod tidy

  echo "Updated ${TARGET_DEPENDENCY} replace version to ${resolved_version}"
}

main "$@"

在上层代码执行以上shell脚本,./shell脚本 commit哈希值

相关推荐
瑶山2 小时前
IDEA 配置Go语言开发环境、GOPATH传统 Go 项目导入
java·golang·intellij-idea
会编程的土豆3 小时前
【go】 Go语言中的 defer:从入门到理解底层机制(讲透版)
开发语言·后端·golang
初心未改HD5 小时前
Go语言Slice切片底层原理深度解析
开发语言·golang
世界尽头与你5 小时前
Go 语言高级函数特性
开发语言·golang
geovindu6 小时前
go: Iterator Pattern
开发语言·设计模式·golang·迭代器模式
不知名的老吴7 小时前
聊一聊年轻的编程语言Golang与Rust
开发语言·golang·rust
初心未改HD8 小时前
Go语言Map底层原理与并发安全深度解析
开发语言·golang
geovindu19 小时前
go: Chain of Responsibility Pattern
开发语言·设计模式·golang·责任链模式
Tomhex1 天前
Go内存逃逸优化技巧
golang