go – Golang import path best practice-ThrowExceptions

Exception or error:

I am currently working on a private project using Golang (and I am new to it).

But I have the problem that I don’t know what is the proper way to define the import path for local packages.

I have the same feeling as the author from this link https://medium.com/@c9s/golang-the-annoying-remote-import-path-c6c7e76517e5

In short, if I host a project foo in Github. I feel strange to use github.com/levin/foo as import path instead of just foo. Wouldn’t it cause much rework if I move my codes to Bitbucket or I host my own git server in AWS?

And worse, I can rewrite my code to change the import path, but how would people using my code in theirs notify the change of repo? And I feel no sense to ask others to update their codes.

I am new to Golang so feel free to say something like “your question is not even valid”.

How to solve:

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.

Answer:

We are also developing a project (privately) and we are hosting it on GitLab and I am well aware that go get doesn’t work well on private repositories (at least as far as i know).

What we did is we created a folder, lets say $GOPATH/src/theproject and clone all the repositories inside that folder.

So far, it works well for us, but you might also think that it is tedious to do that, and it is, but we don’t have any other way to do it. We manually update the code by using git pull.

Answer:

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)

Leave a Reply

Your email address will not be published. Required fields are marked *