2

我有以下项目结构,在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目录中。run同样重要的是,我能够build从项目的根目录获取代码(例如,.env文件位于存储库的根目录)。

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

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

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

1 回答 1

1

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

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

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

请注意,有一个src文件夹——说得委婉一点——并不常见

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

好吧,从根本不使用开始go run,使用go build. 然后尝试构建实际的主包。所有的 go 工具在上效果最好,而不是在文件系统文件夹上。如果您的模块已命名playing.hardball/for-unspecific-reasons并且包 main 在srctry中go build playing.hardball/for-unspecific-reasons/src

即使这不能达到您想要的方式,也可以得到外卖:

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