Go build: “Cannot find package” (even though GOPATH is set)

前端 未结 9 1490
庸人自扰
庸人自扰 2020-12-04 07:35

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 $GO         


        
相关标签:
9条回答
  • 2020-12-04 07:52

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

    go env -w  GO111MODULE=off
    
    0 讨论(0)
  • 2020-12-04 07:54

    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?

    0 讨论(0)
  • 2020-12-04 08:02

    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.

    0 讨论(0)
  • 2020-12-04 08:02

    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.

    0 讨论(0)
  • 2020-12-04 08:09

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

    export PATH=$PATH:/directory/to/go/
    
    0 讨论(0)
  • 2020-12-04 08:14

    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.
    0 讨论(0)
提交回复
热议问题