Golang import path best practice

The answer to your question:

I don't know what is the proper way to define the import path for local packages.

As @JimB said:

If you want to use the Go tools you need to follow the conventions. If you want go get to work, then you need to import it with the full name, otherwise put it wherever you want in GOPATH

So you need to use the complete import path github.com/levin/foo if you want go get to work, and you should do it this way if you expect other people to use your package.

The answer to your second question:

Wouldn't it cause much rework if I move my codes to Bitbucket or I host my own git server in AWS?

There is a way to use a custom domain name as import path and still host your code wherever you want, it's called a vanity import path I think. You just need to add some meta tags to the html file that gets served in the import file that you use.

This article explains how to do it, but in summary, in the file that gets served in your custom domain when the custom import path is accessed, you need to add a go-import meta tag that points to where you hosted the code. The article uses github.com/foo/bar as example of where you are hosting your code and foo.com/bar as your real import path.

So in the file that gets served when accessing foo.com/bar there should be a meta tag like this:

<meta name="go-import" content="golang.org/x/tools git http://github.com/foo/bar">

And you continue to host your code in github. Then if you change the hosting place to your code you just change the value of the meta tag, but all the code that uses the package continue to use the exact same import path "foo.com/bar.

The only issue with this is that now your project can get imported by 2 different paths: foo.com/bar and github.com/foo/bar. To fix this they have canonical imports which only allow the package to be imported using the custom path and not the github one, it's only adding a comment next to the package name on each package file:

package bar // import "foo.com/bar"

This is the only way to avoid the issue you have. You can use @srxf answer if you are using a package that is just going to be used locally just know that the go tools are not going to work with that code (like go get). If you want the code to work as it is intended then this is the way to go.

As a comment, I know it feels silly importing github.com/levin/foo for a local package, but if you use that package in another package (say foo2) and someone else imports foo2, this allows the compiler to know exactly where to get the dependencies for foo2, because all the import in the code include the whole route, not the name of a local file. This way people can always get the dependencies they need for your package without having to include those files in your repo, and without having to configure anything for it to work. It's not perfect but it's the way go works, they call it convention over configuration or something like that.


This question should probably be re-answered as of Go 1.11 with the introduction of Go Modules. Modules can be used to solve this "local path" dilemma as well as pesky projects outside the scope of GOPATH. You may now initialize your project via...

go mod init <main package name>

You may then reference a local package by their package name. Like this...

go mod init app

Then (assuming you have another local package called "models") reference within your file

import (
  "app/models"
)

Refs:

https://github.com/golang/go/wiki/Modules

Accessing local packages within a go module (go 1.11)

Tags:

Import

Go