正文
看源码的一个比较好的思路是:先从宏观上对系统内部模块的调用关系有一个大概的认识。这个过程又分静态分析和动态分析。动态分析很简单,直接对内存数据进行采样即可,比如 Golang 的 pprof。动态分析有一个缺点是依赖于流量,或者说访问数据,不同的访问数据往往会造成不同的调用关系。静态分析的话现在市面上也有很多好用的开源工具,我们今天看一下 Golang 的代码静态依赖分析怎么来做。
Golang 代码的静态分析尤其简单,为什么?Golang 语法方面,我们在调用一个 package 的时候,需要 import。同时,如果我们代码中对一个 package 没有引用而又把包 import 进来,这个时候 Golang 的编译器是会报错的。这两点意味着我们可以通过分析 import 语句块来得到我们包内部的调用关系。
当然尽管上面原理说的比较简单,但是实现起来还是有一些坑。没关系,我帮你们实现了。链接:
github.com/legendtkl/g…
。取名 DAG 也是因为包之间的依赖其实就是一个 DAG。
1. 安装
go get -u github.com/legendtkl/godag
我在实现的时候包里面没有引用第三方包,这样也是为了不能翻墙的同学 go get 无障碍。
2. 使用
以 beego 项目为例,分析其内部的包之间的调用关系。
godag --pkg_name=github.com/astaxie/beego --pkg_path=/Users/kltao/code/go/src/github.com/astaxie/beego --depth=1 --dot_file_path=a.dot
godag 支持四个参数:
-
pkg_name: 要分析的 package 名称,必填
-
pkg_path: package 存放在本地的目录,必填
-
depth: 分析的代码深度。举个例子,如果 depth 为 1,我们则会分析包:beego/cache,beego/context;而如果 depth 为 2,则分析这些包:beego/cache/redis,beego/cache/ssdb 等。
-
dot
file
path: 是我们输出的 dot 文件,下面细说
3. 输出
3.1 dot
godag 会输出一个 .dot 文件。dot 是一种绘图语言,它可以方便你采用图形的方式快速、直观地表达一些想法,比如描述某个问题的解决方案,构思一个程序的流程,澄清一堆貌似散乱无章的事物之间的联系。举个列子,下面列出 dot 文件以及对应的流程图。
digraph graphname {
a -> b -> c;
b -> d;
}
对应流程图。
关于 dot 文件更详细的信息可以参考:
DOT(graph description language)
。我们生产的 dot 文件内容如下。
digraph G {
"beego/utils" -> "beego/session"
"beego/logs" -> "beego/logs"
"beego/utils" -> "beego"
}
3.2 可视化
dot 文件的可视化可以使用 graphviz。graphviz 的安装比较简单,比如 Mac 上安装命令如下
brew install graphviz
dot 文件可视化,使用 dot 命令,比如生成 png 图。