Visualizing your golang project's package structure

What I want to make
I use a pretty simple command line tool called godepgraph
to generate a graph of
package structure for a Golang project; But the problem with it is that it prints
all the dependency packages which it makes a messy and unreadable graph. So I use
a script to generate a graph from packages in a project and it will look like this.

prerequirements
You need to have graphviz and godepgraph installed.
go install github.com/kisielk/godepgraph@latest
brew install graphviz # check the graphviz website if you're not using mac
This works if you’re using go modules. You just need to replace ./cmd/app-name
in the first line with the relative path to the folder where your code’s main
function is.
1MAIN_DIR=./cmd/app-name # <--- here
2REOP_OWNER=$(go list -m | grep -oE '^[^/]+/[^/]+')
3REPO=$(go list -m)
4PACKAGES_GRAPH="$(go mod graph | sed 's/ /\n/g' | grep -oE '^[^@]+')"
5PACKAGES_DEPS="$(go list -deps $MAIN_DIR)"
6ALL_DEPENDENCIES="${PACKAGES_GRAPH}${PACKAGES_DEPS:+ }${PACKAGES_DEPS}"
7EXCLUDED_PACKAGES=$(echo $ALL_DEPENDENCIES | sed 's/ /\n/g' | grep -oE '^[^/]+/[^/]+' | uniq | grep -v $REOP_OWNER | tr '\n' ' ' | sed 's/ $//' | sed 's/ /,/g' | tr '\n' ' ')
8godepgraph -s -ignoreprefixes "$EXCLUDED_PACKAGES" $MAIN_DIR | sed "s|\"$REPO|\"|g" | dot -Tpng -o godepgraph.png
The smarter way to do it is to put it in a bash script file, and put $1
as the
value of MAIN_DIR
. Then you can call your script like script_name ./cmd/app-name
.
But I leave it to you if you wanna do it or not.
Why did I make it so complicated?
Well, I was interested to only have the packages I own to be listed in the graph. So I used following command which is supposed to only include packages with the given prefixes in the chart but it just returned an empty image.
godepgraph -onlyprefixes github.com/mdaliyan ./cmd/app-name | dot -Tpng -o godepgraph.png
So, since I just wanted to get to my graph, I went the other way around and gave it the
packages I didn’t want to include. Because there are many of them and they are
different from project to project, I used go
command line to get all the dependencies
in the project and make a list from them to give it to the -ignoreprefixes
flag. And
here is the same code we had above with detailed explanation.
1# the directory where the main function is
2# e.g. `.` or `./cmd/app-name`
3MAIN_DIR=./cmd/app-name
4
5# the module address of the project, written in `go.mod` file.
6# e.g. `github.com/mdaliyan/app-name`
7REPO=$(go list -m) # github.com/mdaliyan/app-name
8
9# The address of the project owner, written in `go.mod` file.
10# e.g. `github.com/mdaliyan`
11REOP_OWNER=$(go list -m | grep -oE '^[^/]+/[^/]+')
12
13# Collect all the direct and indirect depencencies
14# The command itself prints each of them in a new line
15# but we will get them space separated in one line in
16# our environment variable.
17PACKAGES_GRAPH="$(go mod graph | sed 's/ /\n/g' | grep -oE '^[^@]+')"
18PACKAGES_DEPS="$(go list -deps $MAIN_DIR)"
19
20# Concat all depencencies with a space in between.
21# This list contains many duplications.
22ALL_DEPENDENCIES="${PACKAGES_GRAPH}${PACKAGES_DEPS:+ }${PACKAGES_DEPS}"
23
24# This command contains multiple pipes:
25# 1. replacing space with new line
26# 2. keeping the repository owner's addresses in each line
27# 3. get a unique list out of them
28# 4. remove your own repo owner address from the list
29# ... the rest is to replace new lines with commas and
30# remove the last comma from the end
31EXCLUDED_PACKAGES=$(echo $ALL_DEPENDENCIES | \
32 sed 's/ /\n/g' | \
33 grep -oE '^[^/]+/[^/]+' | \
34 uniq | \
35 grep -v $REOP_OWNER | \
36 tr '\n' ' ' | sed 's/ $//' | sed 's/ /,/g' | tr '\n' ' ')
37
38# This command contains multiple pipes:
39# 1. generates a graph's dot file
40# 2. remove your repository owner address from the links
41# from the dot fileso the nodes in the charts become
42# short and nicer to read
43# 4. generate the graph in png format
44godepgraph -s -ignoreprefixes "$EXCLUDED_PACKAGES" $MAIN_DIR | \
45 sed "s|\"$MODULE|\"|g" | \
46 dot -Tpng -o godepgraph.png