https://github.com/soypat/go-mod-tricks
go.mod file and `go mod` command tricks to make using modules a breeze.
https://github.com/soypat/go-mod-tricks
cheatsheet cheatsheets go go-mod go-module go-modules tutorial
Last synced: 4 months ago
JSON representation
go.mod file and `go mod` command tricks to make using modules a breeze.
- Host: GitHub
- URL: https://github.com/soypat/go-mod-tricks
- Owner: soypat
- Created: 2022-01-25T22:27:13.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2025-04-09T19:38:08.000Z (10 months ago)
- Last Synced: 2025-04-09T20:35:43.143Z (10 months ago)
- Topics: cheatsheet, cheatsheets, go, go-mod, go-module, go-modules, tutorial
- Homepage:
- Size: 6.84 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# go-mod-tricks
go.mod file and `go mod` command tricks to make using modules "a breeze".
1. [go.mod file tricks](#gomod-file)
* [Replace a module with local copy](#replace-a-module-with-local-copy)
* [List modules used in build](#list-modules-used-in-build)
2. [`go mod` command tricks](#go-mod-command)
* [Updating an untagged module to latest version](#updating-an-untagged-module-to-latest-version)
* [Why am I importing x module?](#why-am-i-importing-x-module)
3. [Workspace tricks](#workspace-tricks)
* Workspace initialization
* Replacing third party modules with local modules
* Pitfalls
4. [Other tools](#other-tools)
* [`gomod` dependency graph visualization](#gomod-dependency-graph-visualization)
> "a breeze", really?
No, of course not. Go modules is by far the most complex part of learning Go. The only person who has reached module enlightenment may be Bryan Mills. This document will serve as a cheatsheet to alleviate pain points caused by the complexity for the rest of us. We hope it helps you!
# go.mod file
## Replace a module with local copy
The following line in a `go.mod` file has the effect of compiling the module with a local version of the module.
```
replace github.com/author/dependency => /path/to/local/copy
```
## List modules used in build
The following command lists all modules and their versions used in your build excluding test-only dependencies.
```shell
go list -deps -f '{{with .Module}}{{.Path}} {{.Version}}{{end}}' ./... | sort -u
```
Where `sort -u` excludes repeated entries. Thanks to thepudds on slack for command.
# `go mod` Command
## Updating an untagged module to latest version
To update an untagged module (no vX.X.X semantic versioning in place) in a module run the following:
```shell
cd my-module
go get -u github.com/author/dependency@branch-name
```
where `branch-name` is the name of the branch with the changes you wish to have.If you have recent pushes to the module repository the go tool might miss them since it searches a proxy. To avoid this you can tell the go tool to search the direct source:
```shell
GOPROXY=direct go get -u github.com/author/dependency@branch-name
```
You can also specify a certain commit by replacing `branch-name` with the commit hash:
```shell
go get -u github.com/author/dependency@commit-hash
```
## Using private repository modules
Sometimes at work you need to keep your go modules private under your github organization URL. To do this create the repository like you normally would and configure Go to treat repositories under the organization URL as "private" by setting the `GOPRIVATE` environment variable
```sh
go env -w GOPRIVATE=github.com/YourOrg
```
Next configure git to use ssh to get these modules. Go under the hood uses git for module getting. To do this create a `.gitconfig` file in your home directory, or alternatively at the root of your private repository (you'll need to do this for every private repo if you choose the latter).
```toml
[user]
name = soypat
email = my.git.email@example.com
[url "ssh://git@github.com/"]
insteadOf = https://github.com/
[url "ssh://git@gitlab.com/"]
insteadOf = https://gitlab.com/
```
Remember to add your **PUBLIC** SSH key to your github/gitlab profile you use at your organization. To generate an ssh key and visualize your **PUBLIC** ssh key run the following command and press Enter on all dialog prompts:
```sh
ssh-keygen
```
Next you should have a ssh public key in your `~/.ssh` folder at your home directory which starts with `id` and ends with `.pub`. Visualize it by running the following bash command:
```sh
cat $HOME/.ssh/*.pub
```
This is the key you need to setup for your profile for go get to work with private repositories.
## Why am I importing x module?
To find out how a import is being pulled in you may run the following
```shell
cd my-module
go mod why -m github.com/author/dependency
```
The output of `go mod why` are newline separated import paths where the last one is the package being used in your project:
```
# github.com/author/dependency
my-module
github.com/foo/bar
github.com/author/dependency/some-package
```
In the case above, your module is importing `github.com/foo/bar` which in turn imports `github.com/author/dependency/some-package`.
# Workspace tricks
Go workspaces solve the following problem: **When developing there may come a time when you wish to edit a module you have imported to fix a bug on the side of a third party library, or to add a print statement. Go workspaces enable you to do this in a straightforward way.**
## Workspaces: Initialization
First run the following command to initialize your `go.work` file:
```go
go work init
```
This generates a file named "go.work". Its only contents are a single line with the go version i.e: `go 1.21.0`. A newly created "go.work" file has **no effect** on your program compilation, you must add directives to it first (see next section).
## Workspaces: Replacing a third party module with a local version
1. First you must have an initialized `go.work` file next to your existing `go.mod` file (see first section of [workspace tricks](#workspace-tricks)).
2. You should have also cloned the repository of the go module to your local machine and have it in a nearby directory.
3. Replace the module by running:
```bash
go work use $RELATIVE_PATH_TO_MODULE
```
4. You are done! You may start editing the module in `$RELATIVE_PATH_TO_MODULE` freely and changes will be reflected in your program!
### Practical example
We look at a practical example to build more intuition.
Below is an example directory structure.
```s
parent
├── ours
│ ├── .gitignore
│ ├── go.mod
│ ├── go.work
│ └── main.go
├── module1
│ ├── go.mod
│ └── logic1.go
└── module2
├── go.mod
└── logic2.go
```
For our example we are working in our project inside the `ours` directory. We've already initialized the go.work file in preparation to leverage Go's
We are currently using a remote version of `module1` which we wish to edit. So we've cloned module1 to the same parent directory where our `ours` module resides.
We run the following command from inside `ours` directory
```bash
go work use ../module1
```
The go tool will find the `go.mod` file within this directory, check we are actually using it in our project and finally once it confirms it can actually replace it, edit our `go.work` file adding a `use` directive entry.
Once this is done we may start editing the `module1/logic1.go` file and changes to it will be observed in the `ours` module.
If we wish to also replace `module2` we can just replace `../module1` with `../module2` in the command above.
## Workspaces: Pitfalls
It is important to realize once you start editing your workspaced modules your project will no longer have the same behaviour when someone clones your changes without also uploading your workspaced modules. **It is generally frowned upon to track versions of workspaced changes without including these workspaced modules in your versioning.** And even then, tracking workspaced changes is a very complex task which can lead to unecessary code churn and pain if not done correctly.
Ideally one matches versioning between branches in the module one is primarily working on and the workspaced module, trying to match commit names so that changes can be tracked and reproduced easily. When finally ready to generate a PR one proceeds to create a PR for both the workspaced module and the module using the former.
It is suggested to not include the `go.work` file within versioning unless it is internally agreed upon in your organization. Add the following lines to your `.gitignore` to this effect:
```bash
go.work
go.work.sum
vendor # Excludes vendor directory from `go vendor` command.
```
# Other tools
## `gomod` dependency graph visualization
Generate visual dependency graphs using https://github.com/Helcaraxan/gomod.