"package XXX is not in GOROOT" 在构建 Go 项目时

"package XXX is not in GOROOT" when building a Go project

当我从这个项目中休息时出现了一个奇怪的问题。启动 Goland 后,我在尝试 运行 我的项目时遇到了很多错误。

构建我的一个包时出现的具体错误是: start.go: package project/game is not in GOROOT (C:\Go\src\project\game)

我在 C:\Users\username

下有这样的文件夹结构
go
|-src
   |-project
        |-game
            |-entity
                 |-whatever.go
            |-game_stuff.go
        |-server

我的环境变量是这样的:

GOROOT=C:\Go 
GOPATH=C:\Users\ketchup\go 

对于每个模块(project/game/entity、project/game、project/server),我做了一个 git mod init

构建时,Goland 会尝试运行这个:

C:\Go\bin\go.exe build -o C:\Users\ketchup\AppData\Local\Temp\___go_build_project_server.exe project/server

和return错误。

谁能帮我解决这个问题?自从我上次打开 Goland 时它运行良好,我有点迷茫。甚至不确定要看什么方向 - 我是 Go 的新手,我不确定要看什么文档:\ 谢谢大家!

一个非常愚蠢的结论(主要是我的部分),但我的问题来自在每个文件夹中完成 go mod init。从我在 go mod init 中执行的每个文件夹中删除 go.modgo.dep 后,我可以毫无问题地构建(通过终端)

另外,我在 GoLand 中的包没有被检测到,因为我在设置中启用了 Go 模块。我禁用了它,GoLand 能够索引外部包和我自己的包。

对于确实希望模块在停止这样做后与GoLand一起工作的任何人,请确保在首选项中检查'Enable Go modules integration':

您可能已将 GO111MODULE 设置为“开启”,它会一直运行 mod。关闭 GO111MODULE 可能会解决此问题。

go env -w GO111MODULE=off

我错误地手动更改了 go.mod 文件中的模块名称。修复后,它工作正常。

└── hello
    ├── go.mod
    ├── go.sum
    ├── hello.go
    └── morestrings
        ├── reverse.go
        └── reverse_test.go

摘录hello.go

import (
...
"hello/morestrings"
...
)

运行 go build 在 hello 目录中出现以下错误:

hello.go:5:2: package hello/morestrings is not in GOROOT (/usr/local/go/src/hello/morestrings)

虽然 运行 命令 go mod init 您需要添加文件夹名称,而不是 main.go 页面名称。 喜欢:go mod init confirm_enrlconfirm_enrl 是项目文件夹名称

我在项目布局中遇到了同样的错误

     project
        |- pgk
        |- src
            |-module1
                 |- some.go
            |- main.go

some.go

package module1

...

main.go

import "project/module1"

本来我是通过./module1导入module1,出现错误package module1 is not in GOROOT。我通过import "project/module1".

解决了

PS:根据 golang project layoutsrc 不应该在 golang 项目中。

所以看起来如果你 运行 go mod init 'xxx' xxx 是你项目的核心名称。在那里,主要包的完整名称是 'xxx/main' 所以如果你的项目根文件夹是这样的:

root -> go mod init xxx
 |- main.go -> package "main"
 |- tools
      |- helper.go -> package "tools"

并且您想从 main.go 导入工具包,您需要导入这个“xxx/tools”

我在包名拼写错误时遇到了同样的错误。因此,这可能是此错误背后的根本原因。也许对某人有用。

我在使用 goland default awesomeProject 学习入门教程时遇到了同样的问题。 我在创建项目 运行 之后做了什么这个命令 go mod init example.com/hello 但是我的根目录名称不同于 example.com/hello.

手动编辑 go.mod 文件并将 awesomeProject 替换为 example.com/hello 后,构建成功。

我知道这是大约一年前的事了。我只想与那些在本地文件夹中有模块的人分享相同的经验..

问题是因为您没有将模块发布到像 github 这样的中央位置。 你必须 运行 这个命令告诉 go 这个模块是一个本地模块

go mod edit --replace external_folder_module_name= ../pathItsLocated

我在构建 docker 图像时也遇到了类似的错误。错误是 #19 0.785 controllers/vasaprovider_controller.go:28:2: package vasa-operator/config/configs is not in GOROOT.

在 Dockerfile 中添加 go 文件位置后,它对我有用。我添加的行是:

COPY config/configs config/configs/

COPY --from=builder /workspace/config/configs config/configs/

对于我的情况,只需将我的 go 版本 更新到最新版本即可解决问题。

downloaded the latest binary 并安装了它,boom 一切都已排序!

就我而言,我试图从错误的目录构建。旧目录甚至没有任何 .go 个文件。

确保您的导入语句与您在 mod.

中定义的 module 名称匹配

只需使用 mod 文件初始化项目并开始处理根文件夹。

go mod init <name-anything>

在较新的 Go 版本 (post 1.13) 中,您不需要设置 GOPATHGOBIN 等环境变量

您还需要在项目根目录下有一个 go.mod 文件。这将使该目录成为 Go 模块。这也是 .git/ 所在的位置。这意味着每个存储库只需要一个 go.mod。在项目根目录中,您可以执行 go mod init remote-repo.com/username/repository

我在 macOS 上使用 Homebrew 安装了 Go,所以 GOROOT/opt/homebrew/Cellar/go/1.17.5/libexec。此位置包含标准库和 Go 的 运行 次。

testrun 命令在格式 go COMMAND package_path/xxx 中是 运行。在不指定 package_path ./ 和 运行ning go COMMAND xxx 的情况下,编译器假定模块 xxx 位于 GOROOT 中,并且抛出错误 package xxx is not in GOROOT (path/to/GOROOT/src/xxx) 因为它不存在。

此行为是预期的,因为我们正在使用的包不是 Go SDK 的一部分,即不在 GOROOT 中。我们正在使用的包将最终位于 go 工作区或当前工作目录中。 运行ning go install 编译并将可执行二进制文件放入 $GOBIN(a.k.a $GOPATH/bin - 这里 $GOPATH 是 Go 工作区)。 运行ning go build 从包内部编译并在该目录中放置一个可执行文件。

您没有列出 server/ 包中的文件以及哪个文件具有主要功能,因此我将模拟计算器的 3 个工作流程,每个工作流程都展示了更多的复杂性。最后一个工作流程类似于你的目录结构。

目录结构

版本 1:

  • 软件包入门

  • 基本功能

calculatorv1
├── go.mod                      <- go mod init github.com/yourname/calculatorv1
└── basic/
    ├── add.go
    ├── add_test.go
    ├── main.go
    ├── multiply.go
    └── multiply_test.go

版本 2:

  • 更多功能

  • 多个包

calculatorv2
├── go.mod                      <- go mod init github.com/yourname/calculatorv2
├── main.go
└── basic/
│   ├── add.go
│   ├── add_test.go
│   ├── multiply.go
│   └── multiply_test.go
└─── advanced/
     ├── square.go
     └── square_test.go

版本 3:

  • 更多功能

  • 嵌套包

calculatorv3
├── go.mod                      <- go mod init github.com/yourname/calculatorv3
├── main.go
└── basic/
│   ├── add.go
│   ├── add_test.go
│   ├── multiply.go
│   └── multiply_test.go
└─── advanced/
     ├── square.go
     ├── square_test.go
     └── scientific/
         ├── declog.go
         └── declog_test.go

工作流程

注意: 根据您使用的版本,将 xxx 替换为 basicadvancedadvanced/scientific与.

  • 使用go mod init

    在项目目录(calculatorv1calculatorv2calculatorv3之一)中初始化Go模块
  • 运行 测试

    go test -v ./...(从项目根开始,递归执行所有测试套件)

    go test -v ./xxx(来自项目根目录,运行包“xxx”中的测试套件)

    cd xxx/
    go test -v            # (from inside the package)
    
  • 编译执行包

    go run ./...(从项目根目录开始,递归 运行 除了测试之外的所有 .go 文件)

    go run ./xxx(从项目根目录,运行 "xxx" 包中的所有 .go 文件,除了测试)

    cd xxx
    go run .              # (from inside the package)
    

    注意:只有主包中的文件是可执行的,即具有声明 package main 的文件。这意味着 go run ./xxx 仅适用于版本 1,不适用于版本 2 和 3。因此,对于版本 2 和 3,运行 go run main.go


代码

非常容易填入不完整的位

版本 1

add.go

package main

func addition(x int, y int) int {
    return x + y
}

add_test.go

package main

import "testing"

func TestAdd(t *testing.T) {

    t.Run("adding two positive numbers", func(t *testing.T) {
        sum := addition(2, 2)
        expected := 4
        
        if sum != expected {
            t.Errorf("Expected %d; but got %d", expected, sum)
        }
    })
    
    t.Run("adding two negative numbers", func(t *testing.T) {
        sum := addition(-3, -4)
        expected := -7

        if sum != expected {
            t.Errorf("Expected %d; but got %d", expected, sum)
        }
    })

    t.Run("adding one positive and one negative integer", func(t *testing.T) {
        sum := addition(1, -3)
        expected := -2

        if sum != expected {
            t.Errorf("Expected %d; but got %d", expected, sum)
        }
    })
    
}

main.go

package main

import "fmt"

func main() {
    var num1 int = 1
    var num2 int = 2
    
    sum := addition(num1, num2)
    product := multiplication(num1, num2)

    fmt.Printf("The sum of %d and %d is %d\n", num1, num2, sum)
    fmt.Printf("The multiplication of %d and %d is %d\n", num1, num2, product)
}

版本 2

main.go

package main

import (
    "fmt"
    "github.com/yourname/calculatorv2/basic"
    "github.com/yourname/calculatorv2/advanced"
)

func main() {
    var num1 int = 1
    var num2 int = 2
    
    product := basic.Multiplication(num1, num2)
    square := advanced.Square(num2)

    fmt.Printf("The product of %d and %d is %d\n", num1, num2, product)
    fmt.Printf("The square of %d is %d\n", num2, square)
}

multiply.go

package basic

func Multiplication(x int, y int) int {
    return x * y
}

multiply_test.go

package basic

import "testing"

func TestMultiply(t *testing.T) {

    t.Run("multiplying two positive numbers", func(t *testing.T) {
        sum := Multiplication(2, 2)
        expected := 4
        
        if sum != expected {
            t.Errorf("Expected %d; but got %d", expected, sum)
        }
    })
    
    t.Run("multiplying two negative numbers", func(t *testing.T) {
        sum := Multiplication(-3, -4)
        expected := 12

        if sum != expected {
            t.Errorf("Expected %d; but got %d", expected, sum)
        }
    })

    t.Run("multiplying one positive and one negative integer", func(t *testing.T) {
        sum := Multiplication(1, -3)
        expected := -3

        if sum != expected {
            t.Errorf("Expected %d; but got %d", expected, sum)
        }
    })
    
}

square.go

package advanced

func Square(x int) int {
    return x * x
}

版本 3

main.go

package main

import (
    "fmt"
    "github.com/yourname/calculatorv3/basic"
    "github.com/yourname/calculatorv3/advanced"
    "github.com/yourname/calculatorv3/advanced/scientific"
)

func main() {
    var num1 int = 1
    var num2 int = 2
    var num3 float64 = 2
    
    product := basic.Multiplication(num1, num2)
    square := advanced.Square(num2)
    decimallog := scientific.DecimalLog(num3)

    fmt.Printf("The product of %d and %d is %d\n", num1, num2, product)
    fmt.Printf("The square of %d is %d\n", num2, square)
    fmt.Printf("The decimal log (base 10) of %f is %f\n", num3, decimallog)
}

square.go

package advanced

func Square(x int) int {
    return x * x
}

declog.go

package scientific

import "math"

func DecimalLog(x float64) float64 {
    return math.Log10(x)
}

declog_test.go

package scientific

import "testing"

func TestDecimalLog(t *testing.T) {

    t.Run("adding two positive numbers", func(t *testing.T) {
        sum := DecimalLog(100)
        expected := 2.0
        
        if sum != expected {
            t.Errorf("Expected %f; but got %f", expected, sum)
        }
    })
    
    t.Run("adding two negative numbers", func(t *testing.T) {
        sum := DecimalLog(10)
        expected := 1.0

        if sum != expected {
            t.Errorf("Expected %f; but got %f", expected, sum)
        }
    })
}

我们可以通过在终端上写这个命令来解决这个问题:go env -w GO111MODULE=off

但是执行此命令后,您将无法通过终端使用 go mod init。您必须手动创建“go.mod”文件。

在我的例子中,这是通过更改 goroot 路径引起的。

GOROOT 是定义您的 Go SDK 所在位置的变量

如果您将 goroot 更改为安装 go sdk 的位置,它将起作用

看起来有点好笑,但我遇到了同样的错误,因为 运行ning:

go run build

而不是

go build main.go

所以它表明在 build运行 之后的所有内容都应该有一个可识别的路径。

对我来说,这是因为我的主要方法不在包 main 中

package main

func main() {
{

}