168

I am new to go and working on an example code that I want to localize.

In the original main.go import statement it was:

 import (
    "log"
    "net/http"
    "github.com/foo/bar/myapp/common"
    "github.com/foo/bar/myapp/routers"
)

Now I have common and routers package in /home/me/go/src/myapp

So I converted the import statement to:

import (
    "log"
    "net/http"
    "./common"
    "./routers"
)

But when I run go install myapp I get these errors:

can't load package: /home/me/go/src/myapp/main.go:7:3: local import "./common" in non-local package

Also, when I use common and routers instead of ./common and ./routers in the import statement, I get:

myapp/main.go:7:3: cannot find package "common" in any of:
    /usr/local/go/src/common (from $GOROOT)
    /home/me/go/src/common (from $GOPATH)
myapp/main.go:8:2: cannot find package "routers" in any of:
    /usr/local/go/src/routers (from $GOROOT)
    /home/me/go/src/routers (from $GOPATH)

How can I fix this?

Flimzy
  • 68,325
  • 15
  • 126
  • 165
Karlom
  • 11,123
  • 26
  • 68
  • 111
  • 9
    All imports are "local" regardless of the import path. See ["How to Write Go Code"](https://golang.org/doc/code.html) for a detailed explanation. – JimB Feb 18 '16 at 15:06
  • 86
    @JimB putting aside the philosophical debates, what I am concerned is how to solve the problem mentioned above. – Karlom Feb 19 '16 at 10:33
  • 5
    I'm not trying to make a philosophical statement, I'm literally saying *all* imports happen in your local filesystem; there is never any difference whether they originate from a remote repo or not. Don't try to use relative paths (they work sometimes, but are discouraged), and go through the "How to Write Go Code" document, specifically the section on ["Code Organization"](https://golang.org/doc/code.html#Organization). – JimB Feb 19 '16 at 15:20
  • Does this answer your question? [Accessing local packages within a go module (go 1.11)](https://stackoverflow.com/questions/52026284/accessing-local-packages-within-a-go-module-go-1-11) – Michael Freidgeim Apr 17 '21 at 05:48

9 Answers9

110

Well, I figured out the problem. Basically Go starting path for import is $HOME/go/src

So I just needed to add myapp in front of the package names, that is, the import should be:

import (
    "log"
    "net/http"
    "myapp/common"
    "myapp/routers"
)
Karlom
  • 11,123
  • 26
  • 68
  • 111
56

If you are using Go 1.5 above, you can try to use vendoring feature. It allows you to put your local package under vendor folder and import it with shorter path. In your case, you can put your common and routers folder inside vendor folder so it would be like

myapp/
--vendor/
----common/
----routers/
------middleware/
--main.go

and import it like this

import (
    "common"
    "routers"
    "routers/middleware"
)

This will work because Go will try to lookup your package starting at your project’s vendor directory (if it has at least one .go file) instead of $GOPATH/src.

FYI: You can do more with vendor, because this feature allows you to put "all your dependency’s code" for a package inside your own project's directory so it will be able to always get the same dependencies versions for all builds. It's like npm or pip in python, but you need to manually copy your dependencies to you project, or if you want to make it easy, try to look govendor by Daniel Theophanes

For more learning about this feature, try to look up here

Understanding and Using Vendor Folder by Daniel Theophanes

Understanding Go Dependency Management by Lucas Fernandes da Costa

I hope you or someone else find it helpfully

arimaulana
  • 833
  • 7
  • 6
30

You should have created your package with go mod init e.g. go mod init github.com/my-org/my-package

Now in my-package you have a sub module called utils for example.

main.go
utils
 |- randstr.go

And your randstr.go looks like this:

package utils

func RandStr(n int) string {
    // TODO: Generate random string....
    return "I am a random string"
}

And then anywhere in your app you would use exported functions from the utils package like this, for example in main.go:

package main

import (
    "fmt"

    // "github.com/my-org/my-package" is the module name at the
    // top of your `go.mod`
    "github.com/my-org/my-package/utils"
)

func main() {
    fmt.Printf("Random string: %s\n", utils.RandStr(20))
}
Dominic
  • 56,023
  • 17
  • 130
  • 152
  • 1
    I found your answer to be simple to understand. In general, is it correct to say, that by simply copying the required files in the module directories and following your simple instructions, one can eliminate the use of any Version Control System and still be able to use go modules? I simply do not like the notion of tying version control system to a language's development system and add the related complexities if I can maintain all code, including vendor-ed one locally, by simply copying them. As I get more confident with go, I may integrate use of modules-with-versioning support. – Sunny Aug 23 '21 at 14:50
  • Worked well for me. This should be the accepted answer – kargirwar Sep 07 '21 at 12:12
  • 2
    Thank you, been almost a day trying to understand import/export in go after moving from nodejs. The easiest answer I found to date. – Suraj Mandal Nov 01 '21 at 03:20
22

Import paths are relative to your $GOPATH and $GOROOT environment variables. For example, with the following $GOPATH:

GOPATH=/home/me/go

Packages located in /home/me/go/src/lib/common and /home/me/go/src/lib/routers are imported respectively as:

import (
    "lib/common"
    "lib/routers"
)
JimB
  • 96,249
  • 11
  • 237
  • 229
wlredeye
  • 894
  • 1
  • 9
  • 20
  • Yes, the first example was my mistake. – wlredeye Feb 18 '16 at 12:10
  • What you mean by relative path not supported by the tooling? – wlredeye Feb 18 '16 at 12:24
  • 3
    You can't `go install` packages that uses relative imports. – JimB Feb 18 '16 at 13:01
  • I think its misunderstanding here. I mean relative to GOPATH. Not just relative like "../../mypackage" – wlredeye Feb 18 '16 at 13:22
  • That was in reference to the part you fixed about importing relative to the current directory. Yes, all user imports are relative to `$GOPATH/src`. – JimB Feb 18 '16 at 15:05
  • But I already have `export GOPATH=$HOME/go` in my `.bashrc`. How putting the files in `/lib` make a difference? – Karlom Feb 19 '16 at 10:32
  • to import package you need to add relative to `$GOPATH/src` path to your project. `lib/` is just example – wlredeye Feb 19 '16 at 11:04
  • If you are using Go1.11 above, you can follow this [post](https://levelup.gitconnected.com/import-and-use-local-packages-in-your-go-application-885c35e5624) for keeping the relative path – Kino Oct 19 '21 at 03:56
8

an example:

  1. in ./greetings, do go mod init example.com/greetings

  2. from another module, do go mod edit -replace=example.com/greetings=../greetings

  3. go get example.com/greetings

from the go tutorial

ming xi
  • 131
  • 1
  • 3
6

Local package is a annoying problem in go.

For some projects in our company we decide not use sub packages at all.

  • $ glide install
  • $ go get
  • $ go install

All work.

For some projects we use sub packages, and import local packages with full path:

import "xxxx.gitlab.xx/xxgroup/xxproject/xxsubpackage

But if we fork this project, then the subpackages still refer the original one.

MarAvFe
  • 417
  • 4
  • 15
tangxinfa
  • 1,270
  • 12
  • 12
2

As in the question, the folder structure is:

/home/me/go/src/myapp
                └─ common
                └─ routers

So go to myapp dir

cd /home/me/go/src/myapp

Do

go mod init myapp

This will create a go.mod file which lets Go know the name of the module myapp so that when it’s looking at import paths in any package, it knows not to look elsewhere for myapp

Then you can do the following in the code:

import (
    "log"
    "net/http"
    "myapp/common"
    "myapp/routers"
)

Now package common and routers gets imported.

sunil karki
  • 109
  • 2
  • 1
1

The key is how you name your module in the following command

go mod init <TheNameGiven>

Then refer the modules in the inner folder with,

TheNameGiven/folder

I have found the best solution here... Read More

Chikku Jacob
  • 1,660
  • 1
  • 14
  • 24
0

Try to change the package name with the go mod init command.

So, I have go 1.17, and I have the same import problem. My project directory is $GOPATH/src/myswagger/app-swagger-test. I ran this command into app-swagger-test dir:

go mod init app-swagger-test
go mod tidy

In my new go.mod file the package name is app-swagger-test. For example, this import was wrong:

import (
    ...
    "myswagger/app-swagger-test/internal/generated/restapi"
    "myswagger/app-swagger-test/internal/generated/restapi/operations"
)

So I removed go.mod and go.sum. And I ran next commands into app-swagger-test dir:

go mod init myswagger/app-swagger-test
go mod tidy

After that all imports in the project were imported successfully. In the new go.mod file the first line is:

module myswagger/app-swagger-test

Maybe this information is common, but I did not find it. Thanks!

J.M. Janzen
  • 619
  • 1
  • 8
  • 18