golang 标准库间依赖的可视化展示
博客专区 > ios122 的博客 > 博客详情
golang 标准库间依赖的可视化展示
ios122 发表于2周前
golang 标准库间依赖的可视化展示
  • 发表于 2周前
  • 阅读 2642
  • 收藏 54
  • 点赞 3
  • 评论 5
腾讯云 十分钟定制你的第一个小程序>>>   
摘要: 国庆看完 << Go 语言圣经 >>,总想做点什么,来加深下印象.以可视化的方式展示 golang 标准库之间的依赖,可能是一个比较好的切入点.做之前,简单搜了下相关的内容,网上也要讨论,但是没有发现直接能拿过来用的.标准库之间,是必然存在依赖关系的,不同库被依赖的程度必然是不一样的.但究竟有多大差别呢?

简介

预览 国庆看完 << Go 语言圣经 >>,总想做点什么,来加深下印象.以可视化的方式展示 golang 标准库之间的依赖,可能是一个比较好的切入点.做之前,简单搜了下相关的内容,网上也要讨论,但是没有发现直接能拿过来用的.标准库之间,是必然存在依赖关系的,不同库被依赖的程度必然是不一样的.但究竟有多大差别呢? 以下内容,数据源自真实环境的 golang 1.9 版本的标准库.所以,本文不仅是一篇可视化相关的讨论文章,更是提供了一个可以直接探究 golang 标准库间依赖关系的快速梳理工具.

数据准备

标准库各个包之间的相互关系,可以直接通过命令获取,然后简单变换为一个标准的 JSON 对象: go list -json std 示例输出: { "Dir": "/usr/local/go/src/archive/tar", "ImportPath": "archive/tar", "Name": "tar", "Doc": "Package tar implements access to tar archives.", "Target": "/usr/local/go/pkg/darwin_amd64/archive/tar.a", "Goroot": true, "Standard": true, "StaleReason": "standard package in Go release distribution", "Root": "/usr/local/go", "GoFiles": [ "common.go", "format.go", "reader.go", "stat_atimespec.go", "stat_unix.go", "strconv.go", "writer.go" ], "IgnoredGoFiles": [ "stat_atim.go" ], "Imports": [ "bytes", "errors", "fmt", "io", "io/ioutil", "math", "os", "path", "sort", "strconv", "strings", "syscall", "time" ], "Deps": [ "bytes", "errors", "fmt", "internal/cpu", "internal/poll", "internal/race", "io", "io/ioutil", "math", "os", "path", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf8", "unsafe" ], "TestGoFiles": [ "reader_test.go", "strconv_test.go", "tar_test.go", "writer_test.go" ], "TestImports": [ "bytes", "crypto/md5", "fmt", "internal/testenv", "io", "io/ioutil", "math", "os", "path", "path/filepath", "reflect", "sort", "strings", "testing", "testing/iotest", "time" ], "XTestGoFiles": [ "example_test.go" ], "XTestImports": [ "archive/tar", "bytes", "fmt", "io", "log", "os" ] } 梳理过的数据源,参见: https://raw.githubusercontent.com/ios122/graph-go/master/data.js

可视化原理

主要涉及一下内容:
  • 可视化显示,使用的是 echarts
  • 使用原始数据的 ImportPath 而不是 Name,来作为每个数据节点的唯一id.这样是因为 golang 本身的包命名规范决定的.
  • 使用原始数据的 Imports 字段,来确定标准库包与包之间的相互依赖关系.golang是不允许循环依赖的,所以一些循环依赖相关的问题,不需要考虑.
  • 节点的大小,和包被其他包引入的次数成正相关.这样做,被依赖越多的包,图上最终显示时,就会越大.常用包和不常用包,一目了然.

数据整理

就是把原始数据,处理成 echarts 需要的数据,这里简要说下最核心的思路:
  • echarts 显示相关的代码,很大程度上参考了 graph-npm
  • 节点坐标和颜色,采用随机坐标和颜色,以去除节点和包之间的联系.我认为这样处理,能更纯粹地观察标准库包与包之间的联系.
  • 需要一个 edges 来记录包与包之间的依赖关系.在每次遍历 Imports 时,动态写入.
  • 需要一个 nodes 来记录包自身的一些信息,但是其 size 参数,需要计算过所有依赖关系后再填入.
  • 使用 nodedSize 来记录每个包被依赖的次数,为了提升效率,它是一个字典Map.
/* 将原始数据,转换为图标友好的数据. ImportPath 作为唯一 id 和 标签; Imports 用于计算依赖关系; 节点的大小,取决于被依赖的次数; */ function transData(datas){ /* 存储依赖路径信息. */ let edges = [] /* 存储基础节点信息. */ let nodes = [] /* 节点尺寸.初始是1, 每被引入一次再加1. */ let nodedSize = {} /* 尺寸单位1. */ let unitSize = 1.5 datas.map((data)=>{ let itemId = data.ImportPath nodes.push({ "label": itemId, "attributes": {}, "id": itemId, "size": 1 }) if(data.Imports){ data.Imports.map((importItem)=>{ edges.push({ "sourceID": importItem, "attributes": {}, "targetID": itemId, "size": unitSize }) if(nodedSize[importItem]){ nodedSize[importItem] = nodedSize[importItem] + unitSize }else{ nodedSize[importItem] = unitSize } }) } }) /* 尺寸数据合并到节点上. */ nodes.map((item)=>{ let itemId = item.id if(nodedSize[itemId]){ item.size = nodedSize[itemId] } }) return { nodes,edges } }

效果与源码

相关链接

标签: Go ECharts 可视化
共有 人打赏支持
粉丝 64
博文 56
码字总数 101061
作品 1
评论 (5)
胖纸囧
感谢分享,支持。
sapling123
学习了,支持楼主
Acce1erator
这语言已经明确说了 名字就是go 还golang golang叫个不停
进击的代码

引用来自“Acce1erator”的评论

这语言已经明确说了 名字就是go 还golang golang叫个不停
习惯了估计,他官网网址还仍然是golang.org
ios122

引用来自“进击的代码”的评论

引用来自“Acce1erator”的评论

这语言已经明确说了 名字就是go 还golang golang叫个不停
习惯了估计,他官网网址还仍然是golang.org
+1
×
ios122
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: