构建 Go 项目时出现“package XXX is not in GOROOT”

新手上路,请多包涵

当我从这个项目中休息时,出现了一个奇怪的问题。启动 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

对于每个模块(项目/游戏/实体、项目/游戏、项目/服务器),我做了一个 git mod init

构建时,Goland 将尝试运行:

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

并返回错误。

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

原文由 Michael Shum 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 4.7k
2 个回答

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

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

原文由 Michael Shum 发布,翻译遵循 CC BY-SA 4.0 许可协议

在较新版本(1.13 后)的 Go 中,您不需要设置环境变量,如 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 ./ 并且只是运行 go COMMAND xxx ,编译器假定模块 xxx 位于 GOROOT 中,并抛出错误 package xxx is not in GOROOT (path/to/GOROOT/src/xxx) .

这种行为是预期的,因为我们正在使用的包不是 Go SDK 的一部分,即不在 GOROOT 中。我们正在使用的包将最终位于 go 工作区或当前工作目录中。 Running go install and puts an executable binary in $GOBIN (aka $GOPATH/bin - here $GOPATH is the Go workspace).从包内部运行 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


工作流程

Note: Substitute xxx with basic , advanced , or advanced/scientific depending on the version you’re working with.

  • 在项目目录中初始化GO模块( calculatorv1 go mod init calculatorv2 calculatorv3

  • 运行测试

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

或者

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

或者

  cd xxx/
  go test -v            # (from inside the package)

  • 编译执行包

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

或者

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

或者

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

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


代码

很容易填补不完整的位

版本 1

添加.go

 package main

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

添加测试.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)
        }
    })

}

主程序

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

主程序

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)
}

相乘.go

 package basic

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

乘法测试.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

主程序

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)
        }
    })
}

原文由 Saurabh 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题