go: cmd/go: "go get" should create a replcae line automatically if the get path and moudle path don't match

What version of Go are you using (go version)?

go version go1.12 linux/amd64

Does this issue reproduce with the latest release?

yes

What did you do?

$ go get github.com/go101/tinyrouter@v1.0.1

The module path set in go.mod is go101.org/tinyrouter, not github.com/go101/tinyrouter.

What did you expect to see?

no errors, and automatically create a replace line in go.mod file of the app project after parsing the go-got go.mod file:

replace go101.org/tinyrouter => github.com/go101/tinyrouter v1.0.1

What did you see instead?

go: github.com/go101/tinyrouter@v1.0.1: parsing go.mod: unexpected module path "go101.org/tinyrouter"
go: error loading module requirements

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (5 by maintainers)

Most upvoted comments

@go101 When a user imports go101.org/tinyrouter, the Go command needs to find the location of that repository, so it sends a request to https://go101.org/tinyrouter?go-get=1. That allows people to “register” unique module paths by serving that URL, using existing DNS and HTTPS infrastructure.

If it didn’t work this way, anyone would be able to write module go101.org/tinyrouter in their module. When someone imports go101.org/tinyrouter, we’d have no way to know which one was intended. Replace directives are not intended for this purpose.

Module paths are canonical: if a module sets the path go101.org/tinyrouter in its go.mod, users must import it by that name in module mode (and as @dmitshur said, there must be an HTTPS server there pointing to wherever the repository is located). This constraint makes a lot of things simpler. Packages can only be imported by one name, and there’s much less risk the same package being built multiple times.

replace directives don’t seem like the right solution for this. There are a few limited use cases for them (e.g., a short-term fork of an upstream module), but it’s better to avoid them if at all possible. Keep in mind that replace directives are only effective for builds in the main module, so adding them is very likely to break downstream users.

Please see When should I use the replace directive? on the module wiki for more information on replace.

See Remove import paths for more information on custom imports. These are popularly (but not officially) called “vanity imports”, and there are some articles on setting that up. You definitely need to serve https://go101.org/tinyrouter?go-get=1 though.

I just hope

go get github.com/go101/tinyrouter@v1.0.1

is a shortcut for

go mod edit -replace=go101.org/tinyrouter=github.com/go101/tinyrouter@v1.0.1

I think this a reasonable hope.

@jayconrod

Keep in mind that replace directives are only effective for builds in the main module, so adding them is very likely to break downstream users.

I did run the go get command under the path of main module. My intention of running this command is I hope this command will add a replace line in the go.mod file of the main module.

Do you mean I should not place a replace line in the go.mod file of tinyrouter package? This is not my intention.

@dmitshur

If they did go get website.noexist/tinyrouter, it would fail because https://website.noexist/tinyrouter?go-get=1 would not return the expected go-import meta tag.

I just think it is totally unnecessary to let go get makes a request to https://website.noexist/tinyrouter?go-get=1. When it gets the responses from by calling github.com/go101/tinyrouter@v1.0.1, it has succeeded to get the go.mod file of the package. The go.mod file clearly specifies that the canonical import path of the package is website.noexist/tinyrouter. The information is ~efficient~sufficient, why will the command still make a request to https://website.noexist/tinyrouter?go-get=1?

If go build thinks it is ok, why not go get?

The intention is to avoid my library users being locked down to github.com. I would like they use go101.org/tinyrouter as import paths in their source code. When later, I move the package to another place, such as gitlab.com, users can just modify the line in go.mod, no needs to modify all the import paths in source code.

Here, the go101.org could be anything other than github.com, for example, website.noexist/tinyrouter. I never prepare to create a http service to response the https://go101.org/tinyrouter?go-get=1 request. Is this not ok?