目錄
什麼是 go-callvis?
go-callvis 是一個 Go 程式靜態分析工具,能夠生成互動式的函數呼叫關係圖(Call Graph),以視覺化方式呈現程式碼中函數之間的呼叫關係。
核心特點
- 🎯 視覺化呼叫圖:將複雜的函數呼叫關係以圖形方式呈現
- ⚡ 互動式介面:支援 Web 介面即時瀏覽和操作
- 🔧 多種分析演算法:支援 pointer、cha、rta、static 等分析方式
- 📦 套件過濾:可針對特定套件進行分析,排除不相關的依賴
- 🎨 分組顯示:按套件或類型對函數進行分組,便於理解架構
為什麼選擇 go-callvis?
理解程式碼的困難:
- 大型專案的函數呼叫關係複雜難以追蹤
- 新進成員難以快速理解程式碼架構
- 重構時不確定影響範圍
使用 go-callvis 的優勢:
- 快速掌握專案整體架構
- 找出程式碼中的熱點函數(被大量呼叫)
- 識別循環依賴和耦合問題
- 輔助程式碼審查和重構決策
核心特性
特性 1:多種分析演算法
go-callvis 支援四種呼叫圖分析演算法,各有不同的精確度和效能:
| 演算法 | 說明 | 精確度 | 速度 |
|---|---|---|---|
pointer |
指標分析(預設) | 最高 | 最慢 |
cha |
Class Hierarchy Analysis | 中等 | 快 |
rta |
Rapid Type Analysis | 較高 | 中等 |
static |
靜態分析 | 最低 | 最快 |
# 使用不同演算法
go-callvis -algo pointer ./...
go-callvis -algo cha ./...
go-callvis -algo rta ./...
go-callvis -algo static ./...
特性 2:套件過濾與聚焦
可以指定只分析特定套件,排除標準庫或第三方依賴:
# 只聚焦於主套件
go-callvis -focus main ./cmd/server
# 排除特定套件
go-callvis -ignore "github.com/pkg/errors,fmt" ./...
# 限制分析範圍
go-callvis -limit "github.com/myproject" ./...
特性 3:分組與視覺化選項
# 按套件分組
go-callvis -group pkg ./...
# 按類型分組
go-callvis -group type ./...
# 同時按套件和類型分組
go-callvis -group pkg,type ./...
# 不顯示標準庫
go-callvis -nostd ./...
特性 4:輸出檔案格式
go-callvis 使用 Graphviz 作為繪圖引擎,會產生以下類型的檔案:
DOT 檔案(.gv / .dot)
DOT 是 Graphviz 的圖形描述語言,用純文字定義節點和邊的關係:
digraph callgraph {
// 節點定義
"main.main" [label="main" shape=box];
"api.Handler" [label="Handler" shape=box];
// 邊(呼叫關係)
"main.main" -> "api.Handler";
}
檔案用途:
.gv/.dot:Graphviz 原始描述檔,可手動編輯調整圖形- 可用
dot指令轉換為其他格式
手動轉換 DOT 檔案:
# DOT 轉 SVG
dot -Tsvg callgraph.gv -o callgraph.svg
# DOT 轉 PNG
dot -Tpng callgraph.gv -o callgraph.png
# DOT 轉 PDF
dot -Tpdf callgraph.gv -o callgraph.pdf
輸出格式對照
| 格式 | 副檔名 | 說明 | 適用場景 |
|---|---|---|---|
| DOT | .gv .dot |
Graphviz 原始格式 | 需要後續編輯、版本控制 |
| SVG | .svg |
向量圖 | 網頁嵌入、可縮放文件 |
| PNG | .png |
點陣圖 | 一般圖片用途 |
| JPG | .jpg |
壓縮點陣圖 | 檔案大小優先 |
.pdf |
文件格式 | 列印、正式文件 |
保留 DOT 檔案
# 預設會產生 .gv 檔案在暫存目錄
# 使用 -file 參數可保存輸出
go-callvis -format dot -file callgraph ./...
# 同時產生 .gv 和 .svg
go-callvis -format svg -file callgraph ./...
# 會產生 callgraph.svg,.gv 檔在暫存目錄
# 查看暫存目錄的 .gv 檔案
ls /tmp/*.gv
快速開始
安裝方式
# 方式 1:使用 go install(推薦)
go install github.com/ofabry/go-callvis@latest
# 方式 2:從原始碼安裝
git clone https://github.com/ofabry/go-callvis.git
cd go-callvis
go install
# 安裝 Graphviz(必要依賴)
# macOS
brew install graphviz
# Ubuntu/Debian
sudo apt-get install graphviz
# Windows (使用 chocolatey)
choco install graphviz
驗證安裝
# 檢查 go-callvis
go-callvis -h
# 檢查 Graphviz
dot -V
第一個範例
假設有以下簡單的 Go 專案結構:
myproject/
├── main.go
├── handler/
│ └── handler.go
└── service/
└── service.go
# 進入專案目錄
cd myproject
# 生成呼叫圖並在瀏覽器中開啟
go-callvis ./...
# 輸出 SVG 檔案
go-callvis -format svg -file callgraph ./...
執行結果:
- 預設會啟動 Web 伺服器在
http://localhost:7878 - 在瀏覽器中顯示互動式呼叫圖
- 可以點擊節點查看詳細資訊
配置說明
命令列選項
go-callvis 主要透過命令列參數進行配置:
分析選項
| 選項 | 預設值 | 說明 |
|---|---|---|
-algo |
pointer |
分析演算法:pointer、cha、rta、static |
-tests |
false |
是否包含測試檔案 |
-focus |
主套件 | 聚焦的套件路徑 |
-limit |
- | 限制分析的套件前綴 |
-ignore |
- | 忽略的套件(逗號分隔) |
-include |
- | 額外包含的套件 |
輸出選項
| 選項 | 預設值 | 說明 |
|---|---|---|
-format |
svg |
輸出格式:svg、png、jpg、gif |
-file |
- | 輸出檔案名稱(不含副檔名) |
-http |
:7878 |
Web 伺服器監聽位址 |
-skipbrowser |
false |
不自動開啟瀏覽器 |
視覺化選項
| 選項 | 預設值 | 說明 |
|---|---|---|
-group |
pkg |
分組方式:pkg、type |
-nostd |
false |
不顯示標準庫呼叫 |
-nointer |
false |
不顯示介面呼叫 |
-minlen |
2 |
最小邊長度 |
-nodesep |
0.35 |
節點間距 |
-nodeshape |
box |
節點形狀 |
-nodestyle |
filled,rounded |
節點樣式 |
完整配置範例
# 完整的分析指令範例
go-callvis \
-algo rta \
-focus "github.com/myproject/internal" \
-limit "github.com/myproject" \
-ignore "github.com/myproject/vendor" \
-nostd \
-group pkg,type \
-format svg \
-file architecture \
./cmd/server
常用指令
基本指令
# 分析當前目錄
go-callvis .
# 分析整個專案
go-callvis ./...
# 分析特定套件
go-callvis ./cmd/server
# 分析並輸出檔案
go-callvis -format svg -file output ./...
聚焦與過濾
# 聚焦於特定套件
go-callvis -focus "github.com/myproject/api" ./...
# 限制分析範圍
go-callvis -limit "github.com/myproject" ./...
# 忽略特定套件
go-callvis -ignore "testing,fmt,log" ./...
# 不顯示標準庫
go-callvis -nostd ./...
輸出控制
# 輸出為 SVG
go-callvis -format svg -file callgraph ./...
# 輸出為 PNG
go-callvis -format png -file callgraph ./...
# 指定 Web 伺服器 Port
go-callvis -http :8080 ./...
# 不自動開啟瀏覽器
go-callvis -skipbrowser ./...
分組與樣式
# 按套件分組
go-callvis -group pkg ./...
# 按類型分組
go-callvis -group type ./...
# 同時按套件和類型分組
go-callvis -group pkg,type ./...
# 自訂節點樣式
go-callvis -nodeshape ellipse -nodestyle filled ./...
指令選項速查
| 指令 | 選項 | 說明 |
|---|---|---|
go-callvis ./... |
-algo rta |
使用 RTA 演算法分析 |
go-callvis ./... |
-nostd |
排除標準庫呼叫 |
go-callvis ./... |
-focus pkg |
聚焦特定套件 |
go-callvis ./... |
-format svg -file out |
輸出 SVG 檔案 |
go-callvis ./... |
-tests |
包含測試檔案 |
實戰範例
範例 1:分析簡單專案
目標:分析一個基本的 Web API 專案
專案結構:
api-server/
├── main.go
├── handlers/
│ ├── user.go
│ └── product.go
├── services/
│ ├── user_service.go
│ └── product_service.go
└── repository/
└── db.go
程式碼:
# 進入專案目錄
cd api-server
# 生成整體呼叫圖
go-callvis -nostd -group pkg ./...
說明:
-nostd排除標準庫,讓圖更清晰-group pkg按套件分組顯示
範例 2:聚焦特定模組
情境:只想看 handler 層如何呼叫 service 層
# 聚焦於 handlers 套件
go-callvis \
-focus "github.com/myproject/handlers" \
-limit "github.com/myproject" \
-nostd \
./...
說明:
-focus將 handlers 套件放在中心-limit只顯示專案內的呼叫關係
範例 3:分析介面實作
情境:找出介面的所有實作和呼叫路徑
# 使用 RTA 演算法(較好處理介面)
go-callvis \
-algo rta \
-group type \
-nostd \
./...
說明:
-algo rta較能準確分析介面-group type按類型分組,便於看介面實作
範例 4:生成文件用圖
情境:為技術文件生成架構圖
# 輸出高品質 SVG
go-callvis \
-format svg \
-file architecture-diagram \
-nostd \
-group pkg \
-nointer \
-focus "github.com/myproject/cmd" \
-limit "github.com/myproject" \
./cmd/server
專案結構:
output/
└── architecture-diagram.svg # 可嵌入文件的向量圖
範例 5:分析測試覆蓋
情境:查看測試如何覆蓋程式碼
# 包含測試檔案的分析
go-callvis \
-tests \
-focus "github.com/myproject/services" \
-nostd \
./...
說明:
-tests會將_test.go檔案納入分析- 可以看到測試函數如何呼叫被測程式碼
最佳實踐
1. 漸進式分析
# ✅ 推薦:從入口點開始,逐步展開
go-callvis -focus main ./cmd/server # 先看主程式
go-callvis -focus api ./internal/api # 再看 API 層
go-callvis -focus service ./internal/service # 最後看服務層
# ❌ 不推薦:一次分析整個大型專案
go-callvis ./... # 圖太複雜,難以閱讀
2. 合理使用過濾
# ✅ 推薦:排除不相關的套件
go-callvis \
-nostd \
-ignore "vendor,generated,mock" \
-limit "github.com/myproject" \
./...
# ❌ 不推薦:包含所有東西
go-callvis ./... # 會包含大量第三方庫呼叫
3. 選擇適當的演算法
# ✅ 大型專案使用較快的演算法
go-callvis -algo cha ./... # 較快,精確度足夠
# ✅ 需要精確分析時使用 pointer
go-callvis -algo pointer ./internal/critical # 針對關鍵模組
# ❌ 不推薦:大型專案使用 pointer
go-callvis -algo pointer ./... # 可能非常慢
4. 版本控制呼叫圖
# ✅ 推薦:定期生成並存檔
go-callvis -format svg -file docs/architecture-$(date +%Y%m%d) ./...
# 加入 Makefile
# Makefile
.PHONY: callgraph
callgraph:
go-callvis -format svg -file docs/callgraph -nostd -group pkg ./cmd/server
5. 團隊協作
- 定期更新:將呼叫圖作為 CI 產出物,追蹤架構變化
- 程式碼審查:重大變更時生成前後對比圖
- 新人導覽:用呼叫圖解釋專案架構
常見問題
問題 1:找不到 dot 命令
症狀:
exec: "dot": executable file not found in $PATH
原因: 未安裝 Graphviz
解決方案:
# macOS
brew install graphviz
# Ubuntu/Debian
sudo apt-get install graphviz
# CentOS/RHEL
sudo yum install graphviz
# Windows
choco install graphviz
問題 2:分析速度很慢
問題:大型專案分析時間過長
原因:
- 使用 pointer 演算法(預設)
- 分析範圍太大
解決方案:
# 使用較快的演算法
go-callvis -algo cha ./...
# 或限制分析範圍
go-callvis -limit "github.com/myproject/internal" ./...
# 排除不需要的套件
go-callvis -ignore "vendor,generated" ./...
問題 3:圖太複雜難以閱讀
問題:生成的圖節點太多,無法理解
解決方案:
# 1. 聚焦特定套件
go-callvis -focus "github.com/myproject/api" ./...
# 2. 排除標準庫
go-callvis -nostd ./...
# 3. 排除介面呼叫
go-callvis -nointer ./...
# 4. 限制分析深度
go-callvis -limit "github.com/myproject" ./...
# 5. 組合使用
go-callvis -nostd -nointer -focus main -limit "github.com/myproject" ./...
問題 4:Web 介面無法開啟
問題:執行後瀏覽器沒有反應
解決方案:
# 手動指定 Port
go-callvis -http :8080 ./...
# 檢查是否有程序佔用 Port
lsof -i :7878
# 不使用 Web 介面,直接輸出檔案
go-callvis -format svg -file output -skipbrowser ./...
問題 5:無法分析特定套件
問題:某些套件未出現在圖中
原因:
- 套件被過濾掉
- 沒有從入口點可達的呼叫路徑
解決方案:
# 明確包含該套件
go-callvis -include "github.com/myproject/hidden" ./...
# 更改聚焦套件
go-callvis -focus "github.com/myproject/hidden" ./...
# 檢查是否真的有呼叫關係
go-callvis -algo static ./... # 使用靜態分析
總結
核心要點
go-callvis = 靜態分析 + 視覺化 + 互動介面
關鍵優勢:
- ✅ 快速理解大型專案的程式碼結構
- ✅ 找出函數呼叫的熱點和瓶頸
- ✅ 輔助重構和架構決策
- ✅ 生成技術文件用的架構圖
快速決策指南
| 情境 | 推薦做法 | 說明 |
|---|---|---|
| 新接手專案 | go-callvis -nostd -group pkg ./cmd/main |
從入口點理解架構 |
| 重構前分析 | go-callvis -focus pkg -algo rta ./... |
找出影響範圍 |
| 生成文件 | go-callvis -format svg -file doc ./... |
輸出高品質圖片 |
| 大型專案 | go-callvis -algo cha -limit org ./... |
使用快速演算法 |
| 介面分析 | go-callvis -algo rta -group type ./... |
RTA 較好處理介面 |
常用指令速查
# 基本分析
go-callvis ./...
# 排除標準庫
go-callvis -nostd ./...
# 聚焦特定套件
go-callvis -focus "package/path" ./...
# 輸出 SVG 檔案
go-callvis -format svg -file output ./...
# 快速分析大型專案
go-callvis -algo cha -nostd -limit "myorg" ./...
# 完整參數
go-callvis -algo rta -nostd -group pkg -focus main -limit "myorg" -format svg -file arch ./cmd/server
演算法選擇速查
| 演算法 | 適用場景 | 速度 | 精確度 |
|---|---|---|---|
pointer |
小型專案、需要精確分析 | 慢 | 高 |
cha |
大型專案、快速瀏覽 | 快 | 中 |
rta |
介面分析、中型專案 | 中 | 較高 |
static |
超大型專案、基本結構 | 最快 | 低 |
參考資源
- GitHub:https://github.com/ofabry/go-callvis
- Graphviz 官網:https://graphviz.org/
- Go 靜態分析工具:https://pkg.go.dev/golang.org/x/tools/go/callgraph
建立日期:2025-12-01 最後更新:2025-12-01