设为首页 收藏本站
查看: 843|回复: 0

[经验分享] golang 标准库间依赖的可视化展示

[复制链接]

尚未签到

发表于 2018-9-20 12:19:28 | 显示全部楼层 |阅读模式
简介
DSC0000.png

  国庆看完 >,总想做点什么,来加深下印象.以可视化的方式展示 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>  "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 来记录包自身的一些信息,但是其>
  •   使用 nodedSize 来记录每个包被依赖的次数,为了提升效率,它是一个字典Map.

  

/* 将原始数据,转换为图标友好的数据.
  ImportPath 作为唯一>  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
  }
  
}
  

效果与源码


  • github 源码: https://github.com/ios122/graph-go
  • echarts 在线预览: http://gallery.echartsjs.com/editor.html?c=xSyJNqh8nW
相关链接


  • echarts
  • graph-npm



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-598861-1-1.html 上篇帖子: golang使用vendor目录来管理依赖包 下篇帖子: golang面试题
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表