Versioning Go Modules

Let assume you want to organize multiple modules in a single Github repository like the case below and would like to version them separately.
As an example, the nano project includes different modules: the nano itself and other sub-modules protoc-gen-nano, kafka, cache.

https://github.com/pthethanh/nano
...
├── cmd
│ └── protoc-gen-nano
│ ├── go.mod
│ ├── go.sum
├── plugins
│ ├── broker
│ │ ├── kafka
│ │ │ ├── go.mod
│ │ │ ├── go.sum
│ │ └── nats
│ │ ├── go.mod
│ │ ├── go.sum
│ └── cache
│ └── ristretto
│ ├── go.mod
│ ├── go.sum
├── go.mod
├── go.sum
├── go.work
├── go.work.sum

With the structure above, how can you release a different versions for each modules? Let say nano at v0.0.1, kafka at v0.0.2 and so on?

Thanks to Go & Github, they support a very simple way to tag/release a version for each module base on their path on github repo. Basically, all you ned to do is to tag a module with the following format:

git tag <relative path module from the root dir>/<version>

This means I can release each module at different version like below:

// nano at v0.0.1
git tag -a v0.0.1 -m "Release version v.0.1"
git push origin v0.0.1

// gen nano at v0.0.2
git tag -a cmd/protoc-gen-nano/v0.0.2 -m "Release version v.0.2"
git push origin cmd/protoc-gen-nano/v0.0.2

// kafka at v0.0.3
git tag -a plugins/broker/kafka/v0.0.3 -m "Release version v.0.3"
git push origin plugins/broker/kafka/v0.0.3

// nats at v0.0.2
git tag -a plugins/broker/nats/v0.0.2 -m "Release version v.0.2"
git push origin plugins/broker/nats/v0.0.2

Once tagging & releasing done, you can use them in other modules normally:

require (
github.com/pthethanh/nano v0.0.1
github.com/pthethanh/nano/plugins/broker/kafka v0.0.3
)

That's all! Happy coding!