16

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".

stevenferrer
  • 2,504
  • 1
  • 22
  • 33
Levin Kwong
  • 393
  • 1
  • 3
  • 7
  • 5
    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. – JimB Sep 20 '17 at 03:26

3 Answers3

16

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.

Topo
  • 4,783
  • 9
  • 48
  • 70
  • @Topo Thanks! I may need time to digest. – Levin Kwong Sep 20 '17 at 06:15
  • @Topo Let say I use `github.com/foo/bar` at first, and later I changed to `foo.com/bar`. Also, I use canonical import after the change of repo. What exactly will happen in someone else project that originally has the code `import "github.com/foo/bar"` ??? – Levin Kwong Sep 20 '17 at 06:19
  • 1
    If they keep working with the same version of your code than before, then it will keep working because the restriction is on the go command locally. But if they `git pull` the code to get the version with the new change then they will get this error: `can't load package: package github.com/foo/bar: code in directory $GOPATH/src/github.com/foo/bar expects import "foo.com/bar"`. Also if they try to `go get` the code using the github path it will give them an error. So it's better to do it sooner rather than later. – Topo Sep 20 '17 at 06:29
  • 1
    @LevinKwong Although a quick google search for the error and/or a comment on the project README will probably let them know what the issue is and fix it, so it's not the worst case, but if you are just starting your project I think you should do it. If it's an old project people already use, you can let them know in advance, do the vanity import and then at a later date do the canonical import so they have time to fix it. – Topo Sep 20 '17 at 06:33
4

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)

-1

EDIT: This answer is written in the pre-module days and is OUTDATED. Please see the accepted 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.

stevenferrer
  • 2,504
  • 1
  • 22
  • 33