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
	}
}
效果与源码
- github 源码: https://github.com/ios122/graph-go
 - echarts 在线预览: http://gallery.echartsjs.com/editor.html?c=xSyJNqh8nW
 
相关链接
golang 标准库间依赖的可视化展示的更多相关文章
- Golang 标准库log的实现
		
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gotaly.blog.51cto.com/8861157/1406905 前 ...
 - golang标准库分析之net/rpc
		
net/rpc是golang提供的一个实现rpc的标准库.
 - Golang 标准库提供的Log(一)
		
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gotaly.blog.51cto.com/8861157/1405754 G ...
 - golang 标准库
		
前言 不做文字搬运工,多做思路整理 就是为了能速览标准库,只整理我自己看过的...... 最好能看看英文的 标准库 fmt strconv string 跳转 golang知识库总结
 - golang标准库 context的使用
		
本文索引 问题引入 context包简介 示例 问题引入 goroutine为我们提供了轻量级的并发实现,作为golang最大的亮点之一更是备受推崇. goroutine的简单固然有利于我们的开发,但 ...
 - Golang标准库——io-接口
		
接口 Read相关 Reader Reader接口用于包装基本的读取方法. type Reader interface { //将数据读入到p中,直到读满p或者读取的过程中遇到错误,此时返回的n< ...
 - Golang标准库——io-结构
		
结构 LimitedReader 定义 限制从Reader中读取的字节数. type LimitedReader struct { R Reader // underlying reader N in ...
 - golang 标准库 sync.Map 中 nil 和 expunge 区别
		
本文不是 sync.Map 源码详细解读,而是聚焦 entry 的不同状态,特别是 nil 状态和 expunge 状态的区分. entry 是 sync.Map 存放值的结构体,其值有三种,分别为 ...
 - golang标准库中有些函数只有签名没有函数体是怎么回事?
 
随机推荐
- Nginx + Memcached 实现Session共享的负载均衡
			
session共享 我们在做站点的试试,通常需要保存用户的一些基本信息,比如登录就会用到Session:当使用Nginx做负载均衡的时候,用户浏览站点的时候会被分配到不同的服务器上,此时如果登录后Se ...
 - jQuery对象和DOM对象和字符串之间的转化
			
jQuery对象和DOM对象和字符串之间的转化 字符串---------->jQuery对象 $(HTML字符串): $('<div>我是祖国的一朵小花</div>') ...
 - SVG图案
			
前面的话 给SVG元素应用填充和描边,除了使用纯色和渐变外,还可以使用图案.本文将详细介绍SVG图案 概述 <pattern>可以实现重复的效果,在canvas中被翻译为模式,而在SVG中 ...
 - 第2阶段——编写uboot之硬件初始化和制作链接脚本lds(1)
			
目标: 1.关看门狗 2.设置时钟 3.初始化SDRAM (初始化寄存器以及清除bss段) 4.重定位 (将nand/nor中代码COPY到链接地址上,需要初始化nandflash,读flash) 5 ...
 - tomcat学习笔记
			
1.安装和运行[必须] * 解压apache-tomcat-6.0.35.zip * 位置:不能包含中文和空格 * 运行: %tomcat%/bin/startup.bat * 测试 * http:/ ...
 - 个人作业-2 必应词典安卓APP分析
			
产品: 必应词典 安卓版 第一部分:调研,评测 1.对于这款app的第一印象就是界面不是很美观,页面排版十分混乱,有些功能比较鸡肋,功能也不是很丰富,不过这款app的ui设计相对简洁,让人容易上手,对 ...
 - 1001.A+B Format (20)代码自查(补足版)
			
1001.A+B Format (20)代码自查(补足版) 谢谢畅畅酱的提醒,发现了代码中的不足,把变量名更改成更合理的名字,并且把注释也换成英文啦! 栋哥提供的代码自查的方式也帮助了我发现很多代码中 ...
 - 201521123006 《java程序设计》 第13周学习总结
			
1. 本周学习总结 1.以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.j ...
 - 201521123013 《Java程序设计》第9周学习总结
			
1. 本章学习总结 2. 书面作业 Q1.常用异常题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何避免? 经常出现Class ...
 - Ajax练习题
			
1.使用Ajax跳转处理页面连接数据库,完成下拉列表 首页: <body> <select id="sel"> </select> < ...