Go build: "Cannot find package" (even though GOPATH is set)
Asked Answered
S

16

190

Even though I have GOPATH properly set, I still can't get "go build" or "go run" to find my own packages. What am I doing wrong?

$ echo $GOROOT
/usr/local/go

$ echo $GOPATH
/home/mitchell/go

$ cat ~/main.go
package main
import "foobar"
func main() { }

$ cat /home/mitchell/go/src/foobar.go
package foobar

$ go build main.go
main.go:3:8: import "foobar": cannot find package
Sundew answered 3/11, 2012 at 22:15 Comment(3)
I meet the same problem when I go get github.com/adonovan/gopl.io/tree/master/ch1/helloworld The reason shall be it has no file of name helloworld.go . go get works by matching package name and filename.Improvisator
It may also be that you need to upgrade Go. I had a similar issue where I had existing code using go.mod to define a module. On a test machine I had downloaded the code and was trying to compile it but Go was giving me all sorts of errors related to GOPATH and being unable to find modules. It was Go version 1.7. As soon as I upgraded Go, it worked without issue.Sholeen
Type this is terminal for an up-to-date explanation $ go help gopathLacteal
H
190

It does not work because your foobar.go source file is not in a directory called foobar. go build and go install try to match directories, not source files.

  1. Set $GOPATH to a valid directory, e.g. export GOPATH="$HOME/go"
  2. Move foobar.go to $GOPATH/src/foobar/foobar.go and building should work just fine.

Additional recommended steps:

  1. Add $GOPATH/bin to your $PATH by: PATH="$GOPATH/bin:$PATH"
  2. Move main.go to a subfolder of $GOPATH/src, e.g. $GOPATH/src/test
  3. go install test should now create an executable in $GOPATH/bin that can be called by typing test into your terminal.
Hessian answered 4/11, 2012 at 22:26 Comment(2)
Isn't this a bug? My GOPATH=/usr/local/go-pkgs, so Go looks in /usr/local/go-pkgs/src/<package-name> for the source, but go get puts it in /usr/local/go-pkgs/src/gopkg.in/<package-name>. Why should I have to manually move all of my packages after install? That's just silly.Authenticity
go get normally puts packages into $GOPATH/src/ so if you call go get domain.com/path/to/package it will end up in $GOPATH/src/domain.com/path/to/package. I guess you try to fetch a package from gopkg.in? If so thats absolutly intended behavior and you should just import them with their full name; e.g. import "gopkg.in/yaml.v1" as also described in the docs.Hessian
G
51

Although the accepted answer is still correct about needing to match directories with package names, you really need to migrate to using Go modules instead of using GOPATH. New users who encounter this problem may be confused about the mentions of using GOPATH (as was I), which are now outdated. So, I will try to clear up this issue and provide guidance associated with preventing this issue when using Go modules.

If you're already familiar with Go modules and are experiencing this issue, skip down to my more specific sections below that cover some of the Go conventions that are easy to overlook or forget.

This guide teaches about Go modules: https://golang.org/doc/code.html

Project organization with Go modules

Once you migrate to Go modules, as mentioned in that article, organize the project code as described:

A repository contains one or more modules. A module is a collection of related Go packages that are released together. A Go repository typically contains only one module, located at the root of the repository. A file named go.mod there declares the module path: the import path prefix for all packages within the module. The module contains the packages in the directory containing its go.mod file as well as subdirectories of that directory, up to the next subdirectory containing another go.mod file (if any).

Each module's path not only serves as an import path prefix for its packages, but also indicates where the go command should look to download it. For example, in order to download the module golang.org/x/tools, the go command would consult the repository indicated by https://golang.org/x/tools (described more here).

An import path is a string used to import a package. A package's import path is its module path joined with its subdirectory within the module. For example, the module github.com/google/go-cmp contains a package in the directory cmp/. That package's import path is github.com/google/go-cmp/cmp. Packages in the standard library do not have a module path prefix.

You can initialize your module like this:

$ go mod init github.com/mitchell/foo-app

Your code doesn't need to be located on github.com for it to build. However, it's a best practice to structure your modules as if they will eventually be published.

Understanding what happens when trying to get a package

There's a great article here that talks about what happens when you try to get a package or module: https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16 It discusses where the package is stored and will help you understand why you might be getting this error if you're already using Go modules.

Ensure the imported function has been exported

Note that if you're having trouble accessing a function from another file, you need to ensure that you've exported your function. As described in the first link I provided, a function must begin with an upper-case letter to be exported and made available for importing into other packages.

Names of directories

Another critical detail (as was mentioned in the accepted answer) is that names of directories are what define the names of your packages. (Your package names need to match their directory names.) You can see examples of this here: https://medium.com/rungo/everything-you-need-to-know-about-packages-in-go-b8bac62b74cc With that said, the file containing your main method (i.e., the entry point of your application) is sort of exempt from this requirement.

As an example, I had problems with my imports when using a structure like this:

/my-app
├── go.mod
├── /src
   ├── main.go
   └── /utils
      └── utils.go

I was unable to import the code in utils into my main package.

However, once I put main.go into its own subdirectory, as shown below, my imports worked just fine:

/my-app
├── go.mod
├── /src
   ├── /app
   |  └── main.go
   └── /utils
      └── utils.go

In that example, my go.mod file looks like this:

module git.mydomain.com/path/to/repo/my-app

go 1.14

When I saved main.go after adding a reference to utils.MyFunction(), my IDE automatically pulled in the reference to my package like this:

import "git.mydomain.com/path/to/repo/my-app/src/my-app"

(I'm using VS Code with the Golang extension.)

Notice that the import path included the subdirectory to the package.

Dealing with a private repo

If the code is part of a private repo, you need to run a git command to enable access. Otherwise, you can encounter other errors This article mentions how to do that for private Github, BitBucket, and GitLab repos: https://medium.com/cloud-native-the-gathering/go-modules-with-private-git-repositories-dfe795068db4 This issue is also discussed here: What's the proper way to "go get" a private repository?

Gooseneck answered 15/7, 2020 at 1:20 Comment(3)
that article "Anatomy of Modules in Go" is behind a paywall and is not viewableCircle
When I put my main.go under its own subdirectory, "go install git.mydomain.com/path/to/repo/my-app" does not work any more. It gives the error no Go files in git.mydomain.com/path/to/repo/my-app.Tufted
THIS SHOULD BE THE ACCEPTED ANSWER, go mod init is the fix thisLashing
E
20

I solved this problem by set my go env GO111MODULE to off

go env -w  GO111MODULE=off

Note: setting GO111MODULE=off will turn off the latest GO Modules feature.

Reference: Why is GO111MODULE everywhere, and everything about Go Modules (updated with Go 1.17)

GO111MODULE with Go 1.16

As of Go 1.16, the default behavior is GO111MODULE=on, meaning that if you want to keep using the old GOPATH way, you will have to force Go not to use the Go Modules feature:

export GO111MODULE=off

Egidius answered 23/8, 2020 at 10:24 Comment(0)
R
13

In the recent go versions from 1.14 onwards, we have to do go mod vendor before building or running, since by default go appends -mod=vendor to the go commands. So after doing go mod vendor, if we try to build, we won't face this issue.

Rhino answered 11/9, 2020 at 1:49 Comment(2)
I hope this appears in the search results higher up soon because this is exactly what I needed to know.Hoey
This worked ! go v1.17 . could you explain what's actually happening here, a bit in detail?Fuji
R
10

Edit: since you meant GOPATH, see fasmat's answer (upvoted)

As mentioned in "How do I make go find my package?", you need to put a package xxx in a directory xxx.

See the Go language spec:

package math

A set of files sharing the same PackageName form the implementation of a package.
An implementation may require that all source files for a package inhabit the same directory.

The Code organization mentions:

When building a program that imports the package "widget" the go command looks for src/pkg/widget inside the Go root, and then—if the package source isn't found there—it searches for src/widget inside each workspace in order.

(a "workspace" is a path entry in your GOPATH: that variable can reference multiple paths for your 'src, bin, pkg' to be)


(Original answer)

You also should set GOPATH to ~/go, not GOROOT, as illustrated in "How to Write Go Code".

The Go path is used to resolve import statements. It is implemented by and documented in the go/build package.

The GOPATH environment variable lists places to look for Go code.
On Unix, the value is a colon-separated string.
On Windows, the value is a semicolon-separated string.
On Plan 9, the value is a list.

That is different from GOROOT:

The Go binary distributions assume they will be installed in /usr/local/go (or c:\Go under Windows), but it is possible to install them in a different location.
If you do this, you will need to set the GOROOT environment variable to that directory when using the Go tools.

Retard answered 3/11, 2012 at 22:30 Comment(2)
There is also a short video intro to setting up the GOPATHWilburn
Sorry, I've edited the original question. Everywhere I said GOROOT I meant GOPATH.Sundew
A
3

TL;DR: Follow Go conventions! (lesson learned the hard way), check for old go versions and remove them. Install latest.

For me the solution was different. I worked on a shared Linux server and after verifying my GOPATH and other environment variables several times it still didn't work. I encountered several errors including 'Cannot find package' and 'unrecognized import path'. After trying to reinstall with this solution by the instructions on golang.org (including the uninstall part) still encountered problems.

Took me some time to realize that there's still an old version that hasn't been uninstalled (running go version then which go again... DAHH) which got me to this question and finally solved.

Agley answered 31/1, 2018 at 7:43 Comment(0)
D
3

Running go env -w GO111MODULE=auto worked for me

Douche answered 6/5, 2021 at 19:59 Comment(0)
C
2

Without editing GOPATH or anything, in my case just worked the following:


/app
├── main.go
├── /utils
    └── utils.go

Import packages where needed. This can be unintuitive, because it isn't relative to the app path. You need to add the app in the package path too:

main.go:

package main

import(
   "app/util"  
)

Being in app directory, run:

go mod init app

go get <package/xxx>

go build main.go / go run main.go

You should be good to go.


GOPATH = /home/go

appPath = /home/projects/app

Create a proper go.mod and go.sum with go mod init app (delete old before)

After that resolve all dependencies like missing packages with go get github.com/example/package.

Cagliari answered 22/5, 2021 at 20:0 Comment(0)
R
2

In simple words you can solve the import problem even with GO111MODULE=on with the following syntax for import:

import <your_module_name>/<package_name>

your_module_name -> module name which can be found in the go.mod file of the module as the first line.

example: github.com/nikhilg-hub/todo/ToDoBackend

package_name -> Path to your package within module.

example: orm

So the import statement would look like:

import "github.com/nikhilg-hub/todo/ToDoBackend/orm"

According to me we need to specify the module name + package name because we may need a same package name in two or more different modules.

Note: If you are importing a package from same module still you need to specify the full import path like above.

Rhymester answered 9/1, 2022 at 22:57 Comment(1)
this doesn't workCircle
B
1

If you have a valid $GOROOT and $GOPATH but are developing outside of them, you might get this error if the package (yours or someone else's) hasn't been downloaded.

If that's the case, try go get -d (-d flag prevents installation) to ensure the package is downloaded before you run, build or install.

Biopsy answered 20/11, 2020 at 12:19 Comment(0)
S
1
  • GOROOT should be set to your installation directory (/usr/local/go).
  • GOPATH should be set to your working directory (something like /home/username/project_folder). GOPATH should not be set to GOROOT as your own project may need to install packages, and it's not recommended to have those packages in the Go installation folder. Check out this link for more.
Strew answered 19/6, 2022 at 7:32 Comment(0)
D
0

For me none of the above solutions worked. But my go version was not the latest one. I have downloaded the latest version and replaced the older version in my mac os after that it worked perfectly.

Denby answered 14/5, 2021 at 18:56 Comment(0)
H
0

I had a similar problem when building a docker file:

[1/3] STEP 9/9: RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go
api/v1alpha1/XXX.go:5:2: cannot find package "." in:
        /workspace/client/YYY/YYY.go

This only appeared when building the Dockerfile, building locally worked fine.

The problem turned out to be a missing statement in my Dockerfile:

COPY client/ client/
Helyn answered 8/2, 2022 at 13:23 Comment(0)
H
0

I do not understand why this happens, we must be able to import from wherever our file is in its nest, since I have discovered that if we have more than one nest this will throw an error.

package main

import (
    "fmt" 
    "indexer/source/testPackage3" // this will be show a GOROOT error.
    "indexer/testPackage"
    "indexer/testPackage2"
)

func main() {
    fmt.Println("Agile content indexer -")
    fmt.Println(testPackage.Greeting())
    fmt.Println(testPackage2.Greeting())
    fmt.Println(testPackage3.Greeting())
}


├── testPackage2
│   ├── entry2.go
│   └── source
│       └── entry3.go

To conclude, I just want to tell you, the entry3.go file will not work when imported into my main file, which in this case is (main.go), I do not understand why, therefore, I have simply chosen to use a depth folder in the packages I need to export.

SEE THE STRUCTURE

entry.go, entry2.go will work perfectly when imported, but entry3.go will not work..

In addition, both the directory and the name of the package must be the same so that they work properly when importing them.

Hatchment answered 23/11, 2022 at 19:18 Comment(0)
C
0

In my case was successfully compiled only that way... First. You mast look where is yours GOROOT. To see where it is, use command

$ go env

I put to it simliks linking to my packages directories (my directory's with package files located in some directory where I write a code of main package) To create simlink use this

$ ln -s <path_to_directory_with_package> <path_inside_your_GOROOT>

Second. You mast add all new package in your import part of main package

import (
    "fmt"
    "packag1"
    "os"
    "packag2"
)

and in package name declaration, in go code files, mast be same names, like this

package packag2
package packag1

directories and go file names mast be named same names

$ tree .
.
├── main
├── main.go
├── packag1
│   └── packag1.go
└── packag2
    └── packag2.go

2 directories, 4 files

do not forget to make simlinks

$ tree /usr/local/go/src/
/usr/local/go/src
├── packag1 -> /home/user1name/Desktop/someDeskDir/src/packag1
└── packag2 -> /home/user1name/Desktop/someDeskDir/src/packag2

(I show in this comment only created simlinks by my. In other cases in GOROOT directory well be math more files and directory's)

P.S. I use "Ubuntu 22.04.2 LTS", install GO from archive go1.20.4.linux-amd64.tar.gz, downloaded from https://go.dev/doc/install In other systems mast be difference.

RU-RU-RU-RU

В моем случае компиляция заработала только при такой структуре... Первое. Сначала надо узнать где Ваш GOROOT.Для этого есть команда

$ go env

Туда нужно поместить симлинки на директории где храняться Ваши пакеджи (я привык хранить код в одном месте в какой нибудь директории на рабочем столе, по этому и создаю симлинки в GOROOT. Наверное можно хранить исходники прям в GOROOT или еще как нибудь решить эту проблемму)

Создать симлинки можно этой командой

$ ln -s <path_to_directory_with_package> <path_inside_your_GOROOT>

Второе. Вы должны добавит все новые package в раздел import Вашего main package файла

import (
    "fmt"
    "packag1"
    "os"
    "packag2"
)

и в деклорации имени package, в файле с go кодом,должны быть те же имена

package packag2
package packag1

директории и файлы с кодом на языке go, должны называться точно так же

$ tree .
.
├── main
├── main.go
├── packag1
│   └── packag1.go
└── packag2
    └── packag2.go

2 directories, 4 files

не забудьте сделать симлинки

$ tree /usr/local/go/src/
/usr/local/go/src
├── packag1 -> /home/user1name/Desktop/someDeskDir/src/packag1
└── packag2 -> /home/user1name/Desktop/someDeskDir/src/packag2

(Я показал только те симлинки которые сам создал, обычнов GOROOT директории гораздо больше файлов)

З.Ы. Я работаю на линукс "Ubuntu 22.04.2 LTS" устанавливал GO из скачаного с сайта https://go.dev/doc/install архива go1.20.4.linux-amd64.tar.gz На других системах может быть по другому.

Compensate answered 8/6, 2023 at 11:45 Comment(0)
S
-9

Have you tried adding the absolute directory of go to your 'path'?

export PATH=$PATH:/directory/to/go/
Stig answered 4/11, 2012 at 8:53 Comment(1)
the $PATH has nothing to do with your the path for go packages.Erna

© 2022 - 2024 — McMap. All rights reserved.