【问题标题】:Is there a way to run a Go module from another directory有没有办法从另一个目录运行 Go 模块
【发布时间】:2020-11-11 06:43:10
【问题描述】:

我在GOPATH 之外有以下项目结构。

. // Project root
├── Dockerfile
├── .env
├── README.md
└── src
    ├── main.go
    ├── go.mod
    ├── go.sum
    ├── internal
    │   ├── somepackage
    │   │   ├── main.go
    │   │   └── types.go
    │   ├── someother
    │   │   ├── main.go
    │   │   ├── oauth.go
    │   │   └── types.go
    │   └── models
    │       └── main.go
    └── pkg
        ├── somepackage
        │   └── main.go
        └── anotherpackage
            └── main.go

我想运行位于 src 目录中的 Go 模块代码。 当我cd 进入src 目录和go run .go build . 我的代码时,它可以完美运行。

当我站在项目的根节点时,我无法运行 go run ./srcgo build ./src。我收到以下错误。

src/service.go:8:2: cannot find package "web-service/internal/auth" in any of:
        /usr/lib/go/src/web-service/internal/auth (from $GOROOT)
        /home/miloertas/Packages/go/src/web-service/internal/auth (from $GOPATH)
src/endpoints.go:3:8: cannot find package "web-service/internal/handlers" in any of:
        /usr/lib/go/src/web-service/internal/handlers (from $GOROOT)
        /home/miloertas/Packages/go/src/web-service/internal/handlers (from $GOPATH)

我的源代码保留在这个src 目录中很重要。 同样重要的是,我能够从项目的根目录中使用runbuild 我的代码(例如,.env 文件位于存储库的根目录中)。

因此,我正在从我的项目的根目录中寻找runbuild 我的代码在src 目录中的方法。

我尝试将go.mod 移动到项目的根目录并运行并运行go run ./src,但这会导致其自身的问题:

  • go 命令现在无法定位internalpkg 中的所有子包
  • VSCode 现在丢失了,由于某些原因无法执行测试(主要是因为没有找到所有子包)。

【问题讨论】:

  • 我不知道为什么这个问题被严重否决了,真的。虽然它显示出缺乏关于 Go 的做什么和不做什么的基本知识,但我想说它的表述相当好,清楚地表明 OP 在发布之前进行了研究。
  • 人们会期望像go build ./src/... 这样的东西可以工作,或者会有一个常见的选项意味着“这是我的go.mod所在的项目根目录,从这里开始工作” 喜欢go build --root src ./...,但显然我住在幻想世界。也许回退到一个好的老式 Makefile 并在那里编码你的目标和命令,包裹在 (cd src; go build ./...) 中。

标签: go gopath


【解决方案1】:

我的源代码保留在这个 src 目录中很重要。同样重要的是,我能够从项目的根目录运行和构建我的代码(例如 .env 文件位于存储库的根目录)。

这两个要求是矛盾的。你必须放手一个。

尤其是第二个是没有根据的:不要使用 go run,使用 go build。将查找 .env 文件的路径作为程序的命令行选项(Go 不是 PHP 或 JavaScript,只是 is 没有用于执行二进制文件的项目或源根目录)。或者在某处构建可执行文件,但在项目根目录中执行它。

请注意,拥有src 文件夹是 -- 说得委婉一点 -- 不常见

我尝试将 go.mod 移动到项目的根目录并运行并运行 go run ./src 但这会导致其自身的问题:

好吧,首先不要使用go run,而是使用go build。然后尝试构建实际的主包。所有的 go 工具在 packages 上效果最好,而不是在文件系统文件夹上。如果您的模块名为 playing.hardball/for-unspecific-reasons 并且主包位于 src 中,请尝试使用 go build playing.hardball/for-unspecific-reasons/src

即使这没有达到您想要的效果,也可以外卖:

  • 不要使用go run。原因是多方面的,运行单个文件脚本和加载的footgun基本上适用于所有其他用例。
  • go 工具适用于 import paths。在简单的情况下,可以从文件系统中推断出导入路径。
  • 已编译的可执行文件没有 概念“项目目录”、“源”、“类路径”或其他任何东西,它是一个独立 可执行文件可在任何地方运行,并且完全脱离其来源。
  • 使所有文件系统查找路径成为配置选项(命令行标志或环境变量);提供实用的默认值(例如./);在运行可执行文件时使用它来宣布在哪里可以找到 .env 文件、模板、图标、css 文件等静态内容。

【讨论】:

  • 我想知道这是否可能,如“有没有办法”。我知道我的设计选择非常不寻常,不是“最佳实践”,但这不是我的意思。无论如何,谢谢。
  • 好的:不,没有办法完全按照你想要的方式。您必须至少重新设计解决方案的某些方面。
  • 好的,我想我要改变我的布局了。谢谢你。我建议您在答案的顶部指定它不能实现以避免混淆。
  • “请注意,有一个 src 文件夹——说得委婉一点——不常见。”——可能是因为 go 工具太固执和不灵活,它几乎——正如OP发现的那样,不可能。如果您生活在多模块类型开发的异构世界中,那么建议的布局非常合理。
【解决方案2】:

Go 1.18 开始,现在可以使用Go workspaces 实现这一目标。

使用以下目录结构

parent-dir/
└─ go.work
   hello-world/
   ├─ go.mod
   └─ main.go

您可以使用go run hello-worldparent-dir 运行hello-world 模块。

go.work

go 1.18

use ./hello-world

go.mod

module hello-world

go 1.18

注意:这是可能的,不推荐 @Volker 指出的

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 2011-09-22
    • 2018-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多