go-callvis is a static analysis tool that generates interactive call graphs for Go projects. It uses Graphviz to render the relationships between functions and packages, making it easy to understand code structure and dependencies.
Rqeuirements are straightforward: Go 1.19 or higher must be installed, and analysis commands should be executed from the project root directory.
Upgrading Go
Removing Old Versions
sudo apt remove golang-go golang-1.18-doc golang-1.18-go golang-1.18-src
Installing New Version
Install Go 1.21 directly:
sudo apt install golang-1.21
Setting Environment Variables
sudo vim /etc/profile
Add the following at the end of the file:
export GOROOT=/usr/lib/go-1.21
export GOPATH=$HOME/gowork
export GOBIN=$GOPATH/bin
export PATH=$GOPATH:$GOBIN:$GOROOT/bin:$PATH
Loading the Environment
For the current session:
source /etc/profile
For future sessions, edit ~/.bashrc and add:
source /etc/profile
Analysis Workflow
Using the gorush project as an example—a Gin-based push notification service—to demonstrate the analysis process.
Installing go-callvis
Navigate to the target repository:
cd gorush
Install the tool:
go install github.com/ofabry/go-callvis@master
Run the analysis:
go-callvis ./
Output:
2024/01/28 07:55:35 http serving at http://localhost:7878
2024/01/28 07:55:35 OpenURL error: exec: "xdg-open,x-www-browser,www-browser": executable file not found in $PATH
Opening http://localhost:7878 in a browser displays the generated call graph.
By default, go-callvis identifies the main package as the entry point and aggregates methods by package name. In the rendered graph, each package appears as a node containing its methods. This behavior is controlled by the -group flag, which accepts pkg (default) or type.
Analyzing Specific Packages
To analyze packages other than main, use the -focus flag with the package name and path. The path must point to the package directory (not the project root), and -algo static is required. Without the correct path, go-callvis cannot locate the package.
For instance, to examine the router package located at ~/gorush/router:
go-callvis -focus router -algo static ./
This produces an error:
focus failed, could not find package: router
The correct syntax is:
go-callvis -algo static -focus router ./router/
Syntax:
go-callvis -algo static -focus [package_name] ./[package_path]
Exporting to Files
When browser access is unavailable, export the graph directly. The -format flag specifies the output format, and -file sets the output filename.
go-callvis -algo static \
-focus router \
-format=png \
-file=gorush_router \
./router/
Output:
2024/01/28 08:14:51 writing dot output…
2024/01/28 08:14:51 converting dot to png…
For horizontal layouts that produce overly wide images, use -rankdir to change the drawing direction. Options include LR (left-to-right, default), RL, TB (top-to-bottom), or BT.
go-callvis -algo static \
-focus router \
-format=png \
-file=gorush_router_tb \
-rankdir TB \
./router/
Syntax:
go-callvis -algo static \
-focus [package_name] \
-format=[svg | png | jpg | ...] (default "svg") \
-file=[filename] \
./[package_path]
Simplifying the Call Graph
Complex graphs with extensive information can become noisy. Filter out less relevant details using additional flags:
-nointer: Hides calls to unexported functions-nostd: Omits calls involving standard library packages
The -nostd flag significantly reduces noise by excluding standard library internals, while -nointer focuses attention on public API interactions between packages.
go-callvis -algo static \
-focus router \
-format=png \
-file=gorush_router_filtered \
-nointer -nostd \
./router/
Syntax:
go-callvis -algo static \
-focus [package_name] \
-format=[svg | png | jpg | ...] (default "svg") \
-file=[filename] \
-nointer -nostd \
./[package_path]
Additional Examples
Testing with the Gin framework source code:
git clone https://github.com/gin-gonic/gin.git
cd gin
go install github.com/ofabry/go-callvis@master
go-callvis -algo static -focus gin -format=png -file=gin -nointer -nostd ./