Are there conventions for Go module names in mono-repos with multiple modules?
Asked Answered
G

2

9

In a multi-module repository, should a module name (set via the go.mod module directive) follow the conventions of package naming?

E.g. module github.com/org-name/repo-name/path/to/module-dir

I understand that, whatever the module is named, the packages within the module refer to each other using the module name as prefix. But, from outside the module, there seems to problems if the module name is set to something other than the <host><path-within-repo> pattern. get-ing a package included in the module then gives messages about unrecognized import path.

Is there any cause to name a module differently than <host><path-within-repo> ?

Gifford answered 5/7, 2019 at 11:39 Comment(1)
With Go 1.18/1.19, a Go workspace mode might help working with multiple modules in the same Go project.Quin
B
9

There isn't any hard requirement for referencing modules, although it always good practice to use the domain/repo pattern. So, if you want to reference other modules locally that are not in the GOPATH, you can use the replace directive.

https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive

replace also can be used to inform the go tooling of the relative or absolute on->disk location of modules in a multi-module project, such as:

replace example.com/project/foo => ../foo

Let's say we have the following structure:

├── .gitignore
├── pkg1
│   ├── go.mod
│   └── main.go
└── pkg2
    ├── go.mod
    └── utils.go

pkg1/main.go

package main

import (
    "fmt"
    "local/pkg2"
)

func main() {
    fmt.Println(pkg2.Add(1, 2))

}

pkg1/go.mod

module local/pkg1

go 1.12

require local/pkg2 v0.0.0

replace local/pkg2 => ../pkg2

pkg2/utils.go

package pkg2

func Add(a, b int) int {
    return a + b
}

pkg2/go.mod

module local/pkg2

go 1.12

Running:

cd pkg1
go run main.go

You get:

3

Buggy answered 5/7, 2019 at 12:57 Comment(0)
A
1

If you want to be able to go get a module, it should follow the <host>/repo/path/within/repo pattern.

However, I would suggest stepping back and asking if you really do want a multi-module repo. It adds substantial complexity, it is hard to get right, and usually means more work on an on-going basis.

Russ Cox commented in #26664:

For all but power users, you probably want to adopt the usual convention that one repo = one module. It's important for long-term evolution of code storage options that a repo can contain multiple modules, but it's almost certainly not something you want to do by default.

For more details, see "Organize local code in packages using Go modules".

Axolotl answered 2/8, 2019 at 18:50 Comment(1)
Decades of source control management tells me that having dozens of repos for dozens of modules is a recipe for release management hell. It gets weird fast if you actually re-use modules for several teams and multiple teams are creating feature branches, development branches, release branches, etc. With all the code in a single repo, this is a reasonable proposition (still complex, but that's life in the big city). Note: it does not have to be a monolith. There is lots of middle ground here. But if there are linkage dependencies between modules, they almost always belong in the same repo.Seicento

© 2022 - 2024 — McMap. All rights reserved.