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

I have a weird issue that arose when I took a break from this project. Upon starting up Golang, I'm riddled with errors when trying to run my project.

The specific error, when building one of my packages, is: start.go: package project/game is not in GOROOT (C:\Go\src\project\game)

I have a folder structure as such under C:\Users\username

go
|-src
   |-project
        |-game
            |-entity
                 |-whatever.go
            |-game_stuff.go
        |-server

and my env vars are as such:

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

for each of the modules (project/game/entity, project/game, project/server), I did a git mod init.

When building, Goland will try to run this:

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

and return the error.

Can anyone help me with this issue? Kind of lost since Goland was working fine the last time I opened it. Also not even sure what direction to look at - I'm pretty new to Go and I'm not really sure what documentation to look at :\ Thank you everyone!

ベストアンサー1

In newer versions (post 1.13) of Go, you don't need to set environment variables like GOPATH, GOBIN, etc.

You also need to have a go.mod file at the project root. This will make the directory a Go module. This is also where the .git/ is located. This means that only one go.mod is needed per repository. Inside the project root you could do a go mod init remote-repo.com/username/repository

I installed Go using Homebrew on macOS so GOROOT is /opt/homebrew/Cellar/go/1.17.5/libexec. This location contains the standard library and runtimes for Go.

test and run commands are run in the format go COMMAND package_path/xxx. Without specifying the package_path ./ and just running go COMMAND xxx, the compiler assumes that the module xxx is located in GOROOT, and throws error package xxx is not in GOROOT (path/to/GOROOT/src/xxx) because it doesn't exist.

This behavior is expected because the package we are working with is not part of the Go SDK, i.e., not in GOROOT. The package we are working with will either end up in the go workspace or in the current working directory. Running go install compiles and puts an executable binary in $GOBIN (a.k.a $GOPATH/bin - here $GOPATH is the Go workspace). Running go build from inside a package compiles and puts an execuatble in that directory.

You haven't listed the files inside the server/ package and which file has the main function, so I'll emulate 3 workflows of a calculator each demonstrating more complexity. The last workflow is similar to your directory structure.

Directory Structure

Version 1:

  • Getting started with packages

  • Basic functionality

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

Version 2:

  • More functionality

  • Multiple packages

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

Version 3:

  • Even more functionality

  • Nested packages

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

Workflow

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

  • Initialize Go module in the project directory (one of calculatorv1, calculatorv2, or calculatorv3) using go mod init

  • Run tests

    go test -v ./... (from the project root, recursively execute all test suites)

    OR

    go test -v ./xxx (from the project root, run the test suite in package "xxx")

    OR

    cd xxx/
    go test -v            # (from inside the package)
    
  • Compile and execute 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

追加する

package main

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

追加テスト

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

メイン.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

メイン.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)
}

乗算する

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

スクエアゴー

package advanced

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

バージョン3

メイン.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)
}

スクエアゴー

package advanced

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

デクロッグ

package scientific

import "math"

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

デクロッグテスト

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

おすすめ記事