Does the module name have to include the repo name when you publish a Go module?

3,019 views
Skip to first unread message

Dean Schulze

unread,
Sep 7, 2021, 3:33:27 PM9/7/21
to golang-nuts
If you are going to publish a Go module does the module name have to include the repo name?  I couldn't find this documented anywhere but through trial and error I've discovered that it is required.

I named my module like this and published it to github:

module key-value-mod

In another module I declared it to be a dependency


When I ran go get I got this error:

        module declares its path as: key-value-mod
                but was required as: github.com/dwschulze/key-value-mod

I changed the module's name to include the repo (and retagged that commit and pushed both)


and then it worked.

This is a private repo if that makes any difference.

I also discovered that when you have module problems like this you have to clear the mod cache or you end up getting the same error over and over again.


Jay Conrod

unread,
Sep 7, 2021, 3:51:16 PM9/7/21
to Dean Schulze, golang-nuts
The module path doesn't need to match the repo URL, but if other modules depend on your module, then the go command needs to be able to find your repository given your module path.

The lexical constraints for module paths are documented at https://golang.org/ref/mod#go-mod-file-ident. In short, the go command needs to be able to form a valid URL from the module path, so only certain characters may be used, there must be a dot in the first path element and so on.

The go command looks up the repository location by sending a GET request to https://<module-path>?go-get=1. It looks for an HTML response with a meta tag that says where the module is located. For example, for the module golang.org/x/mod, the go command will request https://golang.org/x/mod?go-get=1 and will get a response with:

<meta name="go-import" content="golang.org/x/mod git https://go.googlesource.com/mod">

That says the module is in a Git repository at https://go.googlesource.com/mod.

That process is explained at https://golang.org/ref/mod#vcs-find. There's a special case for GitHub module paths, so if your module is hosted there, you don't need to stand up a server for that URL. Also, if a path component ends with ".git", ".hg", etc, the go command will use everything up to there as the repository URL without performing the lookup.


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/d7c5cc18-6c54-4379-92fe-f313a2c5bc01n%40googlegroups.com.

Dean Schulze

unread,
Sep 7, 2021, 4:05:17 PM9/7/21
to golang-nuts
Your first paragraph seems to say "no" to my question.  But then this seems to say "yes" to my question

"In short, the go command needs to be able to form a valid URL from the module path,"

In my experience it is a definite yes.

Jay Conrod

unread,
Sep 7, 2021, 4:14:18 PM9/7/21
to Dean Schulze, golang-nuts
The module path needs to be part of a valid URL, but it doesn't have to be the same as the repository URL. That's what my golang.org/x/mod example was meant to demonstrate. The repository is hosted on a different domain.

Amit Saha

unread,
Sep 7, 2021, 4:50:02 PM9/7/21
to Dean Schulze, golang-nuts
I came to this conclusion the same way as you did via trial and error. The go.mod of your module must match its location on the Internet/Network when you are importing it from another module. 

Dean Schulze

unread,
Sep 7, 2021, 6:07:39 PM9/7/21
to golang-nuts
That's an entirely different issue.

The module name in go.mod in both the module itself and any other module that will use the first module has to be a valid URL where the code is hosted, or in your case where you can setup another server (on port 80) with a <meta .../> tag.

I was looking to avoid the tight coupling.

Brian Candler

unread,
Sep 8, 2021, 3:23:42 AM9/8/21
to golang-nuts
There is also the "replace" directive:

mkdir mod1 mod2
cd mod1
go mod init key-value-mod
=== code.go ===
package kv

import (
    "fmt"
)

func DoIt() {
    fmt.Println("Hello")
}

cd ../mod2
go mod init bar
go mod edit -replace=key-value-mod=../mod1
=== prog.go ===
package main

import (
    "key-value-mod"
)

func main() {
    kv.DoIt()
}

go mod tidy
go run .

But this would be very inconvenient for users of this package.  They'd have to know where to download it from, download and unpack it somewhere, and then use 'replace' to say where they'd downloaded it.  Worse, you'd lose any chance of having reproducible builds.

Better to choose a long-term module path like "github.com/dwschulze/key-value-mod", and use replace only if you need to use a local version of this package temporarily, e.g. for testing with a new release before you publish it.
Reply all
Reply to author
Forward
0 new messages