This is a short article with some useful tips I’ve gathered after quiet some time after I began to program in Go.
One of the core features of Go is the ease in which you can import libraries and use them right away in your programming. However, as a beginner, I’ve tried many libraries over the course of my first programs that were meant for the same purpose, ending up using only some of them.
This resulted in many go get
commands which downloaded packages to my $GOPATH/src
I don’t use and will never intend to use.
The question is, how can I know what directories are not imported in any of my projects? Luckily, when I created new Go projects, I'd first put them inside my $GOPATH
and then I'd link their directory to ~/repos/
which is outside of my $GOPATH
.
Besides that, when I came to realise I don’t manage my dependencies smartly at all, I began to take a look at Go modules. This has led me into pulling my Go projects outside of $GOPATH
and use go.mod
files in them which I initilized with:
go mod init github.com/doronbehar/myproject
From here on, the rest of the cleanning process is pretty straight forward, here are the two commands I ran in order to clean both unused Go modules ($GOPATH/pkg/mod/
) and Go packages in $GOPATH/src
:
find ~/repos -maxdepth 2 -name go.mod -execdir zsh -c 'go list -f "{{range \$dep := .Deps}}{{printf \"%s\n\" \$dep}}{{end}}" | xargs go list -f "{{if not .Standard}}{{.ImportPath}}{{end}}"' {} \; | sort -u | awk -F / -v OFS=/ '
{
p = $0
while(--NF > 1) {
if ($0 in paths) next
}
print p
paths[p]
}' | sort -u > ~/not-delete.txt
This command is based on what @pmcgrath examplified in his article and I shamelessly used and extended for my own cause. I used find
so this command will run in every directory where go.mod
is found (every project of mine) and I’ve had to use zsh
to wrap @pmcgrath’s command which includes a shell pipe (|
).
After I got all of the pacakges imported in all of my projects, I sorted these (sort -u
) and filtered them with an awk
script stolen from a StackExchange QA. It’s job is to filter directories already contained in previous directories so the list will be more concise.
https://unix.stackexchange.com/a/362578/135796
Finaly, everything is sorted and filtered with only unique values (sort -u
) and piped to a file ~/not-delete.txt
. This file will be used in the following commands that do 2 different things:
As I said before, if you strictly use Go modules in all of your projects and you never use ./vendor
style dependencies, you can remove all of your $GOPATH/src
. All your imports will use $GOPATH/pkg/mod/
as the base path for the packages. Never the less, I’ll show how to delete all unused modules in GOPATH/pkg/mod
:
As most of the dependencies come from GitHub, We can cd
to $GOPATH/pkg/mod
and run the following:
find github.com -mindepth 2 -maxdepth 2 -type d -not -exec grep -q {} ~/not-delete.txt \; -print -exec rm -r {} \;
For every package from github.com
, we check if it matches something in our list of packages we don’t want to delete (~/not-delete.txt
) and only if it doesn’t (mind the -not
flag find
gets!), we remove it with rm -r
I hope this may help for anyone who reads this. It has certainly helped me to note this for my self so I could rehearse this process when I’ll feel like it’s time to clean up unused imports in $GOPATH/pkg/mod
.