【问题标题】:How to setup protobuf, grpc and Go modules in a monorepo?如何在 monorepo 中设置 protobuf、grpc 和 Go 模块?
【发布时间】:2019-12-13 06:38:04
【问题描述】:

我正在尝试在 Go 中创建一个基于微服务的 API,非常基础,只是为了学习一些东西。我必须实现三个主要目标。

  1. Monorepo。
  2. 能够根据需要使用不同的后端语言(即,Go 中的一种微服务,Node.js 中的两种微服务,Python 中的一种)。
  3. 使用 gRPC。

目前我的结构看起来像这样(并且存储在~/Projects/tkg,在 GOPATH 之外)。

每个“服务”都应该是一个独立的应用程序,用“whatever”编写。如您所见,我有一个 Go 服务和一个 React 前端应用程序。此外,还有一个 Makefile,我想用它来构建东西,但我可能会转向 shell 脚本、Docker 等等。没关系。

所以现在的问题。如何使生成的 proto 文件在此设置中正常运行?我想我对 Go 模块和包不太了解,因为我无法设置它,所以articles.go(来自cmd)可以访问生成的api/article.pb.go。怎么做?

// services/articles/go.mod
module tkg/services/articles

go 1.12

require (
    github.com/golang/protobuf v1.3.2
    google.golang.org/grpc v1.22.1
)
// services/articles/cmd/article.go
package main

import (
    pb "tkg/services/articles/api/article"
)

type repository interface {
    Create(*pb.Article) (*pb.Article, error)
}

func main() {

}
// services/articles/api/article.proto
syntax = "proto3";

package article;
option go_package = "tkg/services/articles/api/article";
...
// Makefile
build:
    protoc services/articles/api/article.proto --go_out=.

我在 go.mod 中尝试了各种不同的包名,在 proto 文件中尝试了不同的 go_packages,我尝试了不同的 protoc 命令和路径。我敢打赌,这很愚蠢,对于精通 Go 的人来说这是非常明显的,但对于像我这样来自 Node.js 背景的人来说,无法做到import "../api/article.pb.go" 令人愤怒。 :(

我得到的错误是:could not import tkg/services/articles/api/article (no parsed files for package tkg/services/articles/api/article)。当然,包名称的值不同。这两天我一直在尝试解决它。​​

你会如何解决这个问题?

【问题讨论】:

    标签: go protocol-buffers grpc go-modules grpc-go


    【解决方案1】:

    如果您在与.proto 文件(推荐)相同的目录中生成.pb.go 文件,那么您的导入路径应为:

    import (
        pb "tkg/services/articles/api"
    )
    

    (不是tkg/services/articles/api/article。)

    Go 包是单个目录中 .go 文件的集合——每个文件都有相同的package XYZ 第一行——其中 XYZ 是包名。因此,在导入包时,使用包基目录 - 不包括任何 .go 文件名。


    编辑:(这太长了,无法放入评论):

    我会退后一步,考虑一下您整个项目的基本目录。

    标准 go 包通常是单个单词,例如 timesync 等,因为它们是 go 标准库的一部分。所有其他软件包都应具有完整的 Internet 路径。这些通常匹配一个 git repo 地址(例如"github.com/boltdb/bolt") - 但并不总是例如("gopkg.in/yaml.v2")。这实际上优于集中托管的 NPM 包模型——因为它可以轻松地从任何 repo 主机中提取包。此外,由于存储库被克隆到本地磁盘 - 这些相同的路径可以首先存在于您的本地磁盘上(在它们被托管在互联网上之前,例如用于开发目的)。

    所以我建议您将本地基本目录命名为:

    github.com/myname/myproj/tkg/services/...
    

    然后确保您基于此目录结构导入包,例如

    import "github.com/myname/myproj/tkg/services/api"
    

    如果 go build 没有获取生成的 (.pb.go) 代码,则说明您的 GOPATH 有问题,或者如果使用新的 go-modules 您的 go.mod 设置。

    【讨论】:

    • 不幸的是,这似乎还不够。我在api 文件夹中生成.pb.go 文件(目前在proto 文件中尝试protoc services/articles/api/article.proto --go_out=..option go_package = "tkg/services/articles/api";articles.go 文件仍然看不到它。生成的Go 文件有package api 但@ 987654341@ 产生同样的错误。
    • 我用一些通用指针更新了答案。 import pb 基本上是一种用代码重命名包的方便语法 - 使用 pb 清楚地表明它指的是 protobuf 类型的包。如果您没有使用import pb,那么您可以通过实际的包名称简单地引用您的 protobuf 结构,例如api.Article
    • 我也尝试过使用互联网路径。问题是我不想在我的本地系统上创建一个奇怪的路径,所以 Go 很高兴,因为该项目中可能有不同的语言(Python、Node.js)并且它们并不那么贪婪。项目的本地路径必须保持~/Projects/tkg。这个特定的 Go 应用程序应该能够包含在 ~/Projects/tkg/services/articles 中。我将尝试做更多的研究并回到 Go 包的基础知识。在 GOPATH 之外使用时,它们看起来真的很不直观。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-09
    • 2021-09-08
    • 2021-04-24
    • 2020-03-12
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    相关资源
    最近更新 更多