使用 Golang 代码生成图表的开源库对比
本文的目标读者
对用 Golang 代码生成折线图、扇形图等图表有兴趣的朋友。
本文摘要
主要介绍 Go 中用以绘图的开源库,分别是:
- GitHub - wcharczuk/go-chart: go chart is a basic charting library in go.
- GitHub - vicanso/go-charts: A charts library for Golang
- GitHub - vdobler/chart: Provide basic charts in go
- GitHub - gonum/plot: A repository for plotting and visualizing data
- GitHub - go-echarts/go-echarts: The adorable charts library for Golang
我的需求是生成一个时间轴类型折线图的图片插入到我的报告中,前面两个库与我的需求比较符合,所以我会着重介绍;后面三个库不满足我的需求,在本文会大略带过。如果懒得看正文,这是我总结的表格:
| go-chart | go-charts | chart | plot | go-echarts | |
|---|---|---|---|---|---|
| 使用文档/示例完善 | |||||
| 学习成本 | 中 | 低 | 高 | 低 | 低 |
| 支持的图表种类 | 少 | 少 | 少 | 中 | 多 |
| 支持时间轴 | |||||
| 支持输出图片 | |||||
| 支持设置标签 | |||||
| 支持折线图 | |||||
| 支持自定义图表 | |||||
| UI美观 | ️️️ | ️️️️ | ️️ | ️️ | ️️️️️ |
还有一些库,例如gg和 Go 内部自带的 image/draw 包,在这里就不介绍了,因为它们俩都属于是绘制基础图形(圆形、正方形和矩形等)或者是对图像本身进行旋转、缩放、添加文字等处理的,与本文所讨论的绘制图表不太一样。
go-chart
go-chart是一个简单的 Golang 原生图表库,支持时间序列和连续折线图。因此,go-chart 其实对数据量特别多的情况无法很好地适应,以及如果要在图表中使用中文时,需要额外修改字体为支持中文的字体。
官方效果图
曲线图

单轴折线图

双轴折线图

饼状图

柱状图

安装
go get -u github.com/wcharczuk/go-chart
实际使用
我的需求是,从 influxdb 查询数据,再将数据渲染为折线图,代码如下:
/*
前面省略查询 influxdb 过程
*/
xValue := []string{}
yValue := []float64{}
// 处理查询到的结果数据
for _, value := range allRequest[0].Series[0].Values {
if value[1] == nil {
yValue = append(yValue, 0)
t := value[0].(string)
xValue = append(xValue, t)
} else {
fmt.Println("value:", value[1])
x, _ := value[1].(json.Number)
s, _ := x.Float64()
yValue = append(yValue, s)
fmt.Println(reflect.TypeOf(value[0]))
t := value[0].(string)
xValue = append(xValue, t)
}
}
// 时间轴的显示格式
format := chart.TimeValueFormatterWithFormat("15:04")
lenX := len(xValue)
// X轴内容 xValues 及 X轴坐标 ticks
var xValues []time.Time
var ticks []chart.Tick
for i := 0; i < lenX; i++ {
t, _ := time.Parse(
time.RFC3339,
xValue[i])
x := t.Local()
xValues = append(xValues, x)
ticks = append(ticks, chart.Tick{Value: getNsec(t), Label: format(t)})
}
// 定义曲线
var series []chart.Series
series = append(series, chart.TimeSeries{
XValues: xValues,
YValues: yValue,
Style: chart.Style{
StrokeColor: chart.GetDefaultColor(0).WithAlpha(64),
FillColor: drawing.ColorFromHex("9ADFEA"),
},
})
// 设置图表的样式
lineChartStyle := chart.Style{
Padding: chart.Box{
Top: 30,
Left: 30,
Right: 30,
Bottom: 30,
},
}
graph := chart.Chart{
Title: "All Requests",
Background: lineChartStyle,
Width: 1280,
Height: 500,
XAxis: chart.XAxis{
Name: "",
ValueFormatter: format,
Ticks: ticks,
},
YAxis: chart.YAxis{
Name: "",
},
Series: series,
}
graph.Elements = []chart.Renderable{
chart.LegendLeft(&graph),
}
// 生成图片
var imgContent bytes.Buffer
err = graph.Render(chart.PNG, &imgContent)
if err != nil {
fmt.Println(err)
}
f, _ := os.Create("test.png")
_, _ = f.Write(imgContent.Bytes())
这里查询了10分钟的数据,生成的图片为

可以看到图表上的 x 轴已经看不清了,这是因为数据点非常多,而 go-chart 没有对此进行适配。
在数据点较少的情况下,比如只查询1分钟的数据,生成的图片为:

优点
- 图表的自定义程度高,例如可以选择给曲线填充颜色等
缺点
- 使用比较复杂
我想画的图表的 x 轴是时间轴类型,在这个库中绘制时间轴类型的 x 轴需要额外把数据进行处理为Time.time类型。如使用float64类型的 x 轴的代码会比较简单,示例如下:
graph := chart.Chart{
Series: []chart.Series{
chart.ContinuousSeries{
XValues: []float64{1.0, 2.0, 3.0, 4.0},
YValues: []float64{1.0, 2.0, 3.0, 4.0},
},
},
}
buffer := bytes.NewBuffer([]byte{})
err := graph.Render(chart.PNG, buffer)
- 图表的样式不够精美
下面有go-charts的 demo 图,可以对比一下,确实是不如它好看。
go-charts
Go-charts 是国内的程序员在 go-chart 的基础上优化了图表的生成方式,同时还优化了图表的样式。目前支持 line, bar, horizontal bar, pie ,radar, funnel 以及table类型的图表。
官方效果图
主题为 light与 grafana 。

安装
go get -u github.com/vicanso/go-charts/v2
实际使用
同样是从 influxdb 查询数据,再处理数据生成图表,代码如下:
xValue := []string{}
yValue := [][]float64{}
// 处理结果
for _, value := range allRequest[0].Series[0].Values {
tempY := []float64{}
resultX := value[0].(string)
xValue = append(xValue, resultX)
number, _ := value[1].(json.Number)
resultY, _ := number.Float64()
tempY = append(tempY, resultY)
}
// 对 x 轴格式化 原:2022-07-29T09:24:10Z,新:09:24:10
formatXValue := []string{}
for _, x := range xValue {
formatTime, err := time.Parse(time.RFC3339, x)
if err != nil {
}
formatX := formatTime.Local().Format("15:04:05")
formatXValue = append(formatXValue, formatX)
}
f := false // 设置 x 轴的样式
// 字体文件需要自行下载
buff, err := ioutil.ReadFile("./TencentSans-W7.ttf")
if err != nil {
panic(err)
}
err = charts.InstallFont("noto", buff)
if err != nil {
panic(err)
}
// 渲染图表
p, err := charts.LineRender(
yValue,
charts.FontFamilyOptionFunc("noto"),
charts.TitleTextOptionFunc("全部请求"),
charts.XAxisDataOptionFunc(xValue),
func(opt *charts.ChartOption) {
opt.XAxis.BoundaryGap = &f
opt.Padding = charts.Box{Left: 20, Right: 50, Top: 20, Bottom: 20}
},
charts.ThemeOptionFunc("grafana"),
charts.WidthOptionFunc(1000),
)
查询10分钟的数据,生成的效果图为:

如果将主题换为 light,效果图如下

如果只查询1分钟的数据,效果图如下

从上面的效果图中可以发现,go-charts在数据量比较大的情况下,优化了 x 轴的展示,让数据不会挤在一起;以及样式也更好看一点。
优点
- 样式好看
看上面的图,一目了然 - 使用简单
从代码中也可以看出来,go-charts对 x 轴和 y 轴的类型做了额外一层封装,x 轴的类型为string,y 轴的类型为[][]float64,只需要传相应类型的数据就可以直接渲染图表。
并且由于 y 轴的[]float64就表示一条曲线,所以如果要在图表中增加渲染的曲线也比在go-chart中要更简单——直接给 y 轴数据 append 一个新的[]float64数据即可。
缺点
自定义的自由度没有
go-chart高
例如go-charts中暂不支持用颜色填充曲线,以及不能自定义曲线的颜色等。当曲线超过9条后,曲线的颜色会开始重复

作者的回复是他自己的使用场景只需要用到5条曲线左右,建议如果涉及到太多的曲线,最好分开画图。
不过都不是什么大问题,是一个很好用的开源库。
chart
前面这三个库的名字真是太像了,并且这三个库都提供基础图表的绘制功能。但是这个库更关注自动缩放、误差线和对数图等图表,并且对漂亮UI完全不在乎。
官方效果图

安装
go get -u github.com/vdobler/chart
详细说明
这个库支持的图表类型有
- 带状图
- 散点图/函数图
- 直方图
- 条形图和分类条形图
- 扇形图/环形图
- 箱形图
由上所述,这个介绍为“Provide basic charts“的开源库并不支持我需要的折线图……
以及在介绍里面,这个库有以下几个特点:
- 轴的值可以是线性、对数、分类或者时间/日期轴。
- 自动缩放具有很多选项。
- 抽动和标签的精细控制。
输出格式有txtg、svgg和imgg这三种格式
plot
plot的前身是code.google.com/p/plotinum,它提供了用于 Go 中构建和绘制图表的 API,主要用于将数据可视化。
官方效果图
默认样式

更细粒度的控制

自定义刻度线

带误差的点

条形图

函数

直方图

垂直箱形图

水平箱形图

四分位图

气泡图

安装
go get gonum.org/v1/plot/...
详细说明
plot库其实包含以下四个部分:
plot:提供了布局和绘图的简单接口;plotter:使用plot提供的接口实现了一组标准的绘图器,例如散点图、条形图、箱状图等。可以使用plotter提供的接口实现自己的绘图器;plotutil:为绘制常见图形提供简便的方法;vg:封装各种后端,并提供了一个通用矢量图形 API。
引自《Go 每日一库之 plot》
由上所述,我在使用 plot 库时,发现里面自带的基本API不能满足我的需求——我需要一个时间轴作为 x 轴,但是plot库默认的API中 x 轴只支持float64类型的数据。
但是在plotter中,你可以自定义一个绘图器实现一些特殊的需求,以及你还可以使用社区制作的绘图器,可以在这个网页中查看其中一部分社区绘图器:Community Plotters · gonum/plot Wiki · GitHub。
一些社区绘图器的示例图:


2. GitHub - pplcc/plotext: Extensions and custom plotters for the gonum plot packages
go-echarts
go-echarts是一个专注数据可视化的图表库,参考了pyecharts的一些设计思想;目前有 v1 和 v2 两个版本,其中 v1 已经不再维护。
官方效果图


安装
go get -u github.com/go-echarts/go-echarts/v2
详细介绍
go-echarts是通过实现Apache ECharts的相关接口,来轻松生成全面又美观的图表。
因此,在编写完生成图表的代码后,你还需要将图表渲染成一个HTML文件,或者是用一个HTTP服务器去渲染图表,如图:

以及这个开源库渲染出来的图表也是这几个库里面最美观的(毕竟是用HTML代码渲染出来的)
总结
本文介绍了Go中最主要的几个绘制图表的绘图库,其中对最为接近的两个开源库go-chart和go-charts进行了比较详细的对比,其余三个开源库chart、plot和go-echarts则是简单介绍了一下。
这些开源库各有各的特点,没有绝对的优劣,希望能在大家需要挑选开源库时给予一些参考。
使用 Golang 代码生成图表的开源库对比的更多相关文章
- DICOM:DICOM三大开源库对比分析之“数据加载”
背景: 上一篇博文DICOM:DICOM万能编辑工具之Sante DICOM Editor介绍了DICOM万能编辑工具,在日常使用过程中发现,“只要Sante DICOM Editor打不开的数据,基 ...
- 【GoLang】GoLang 微服务、开源库等参考资料
参考资料: GoLang书籍: https://github.com/dariubs/GoBooksGo名库: https://github.com/Unknwon/go-rock-libraries ...
- Caffe、TensorFlow、MXnet三个开源库对比
库名称 开发语言 支持接口 安装难度(ubuntu) 文档风格 示例 支持模型 上手难易 Caffe c++/cuda c++/python/matlab *** * *** CNN ** MXNet ...
- Caffe、TensorFlow、MXnet三个开源库对比+主流分类模型对比
库名称 开发语言 支持接口 安装难度(ubuntu) 文档风格 示例 支持模型 上手难易 Caffe c++/cuda c++/python/matlab *** * *** CNN ** MXNet ...
- 各种Android UI开源框架 开源库
各种Android UI开源框架 开源库 转 https://blog.csdn.net/zhangdi_gdk2016/article/details/84643668 自己总结的Android开源 ...
- Java下好用的开源库推荐
作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文想介绍下自己在Java下做开发使用到的一些开源的优秀编程库,会不定 ...
- 在别的地方看的<<给程序员介绍一些C++开源库>>,记录给大家共同学习
首先说明这篇文章不是出自我手,大家共同学习. 引用地址:http://oss.org.cn/?action-viewnews-itemid-61998. C++开源库,欢迎补充. C++在“商业应用” ...
- [转贴]C++开源库
C++在“商业应用”方面,曾经是天下第一的开发语言,但这一 桂冠已经被java抢走多年.因为当今商业应用程序类型,已经从桌面应用迅速转移成Web应 用.当Java横行天下之后,MS又突然发力,搞出C# ...
- C/C++ 开源库及示例代码
C/C++ 开源库及示例代码 Table of Contents 说明 1 综合性的库 2 数据结构 & 算法 2.1 容器 2.1.1 标准容器 2.1.2 Lockfree 的容器 2.1 ...
随机推荐
- vue大型电商项目尚品汇(前台篇)day05
紧急更新第二弹,然后就剩下最后一弹,也就是整个前台的项目 一.购物车 1.加入购物车(新知识点) 加入到购物车是需要接口操作的,因为我们需要将用户的加入到购物车的保存到服务器数据库,你的账号后面才会在 ...
- Java添加条形码到PDF表格
条码的应用已深入生活和工作的方方面面.在处理条码时,常需要和各种文档格式相结合.当需要在文档中插入.编辑或者删除条码时,可借助于一些专业的类库工具来实现.本文,以操作PDF文件为例,介绍如何在编辑表格 ...
- DevStream 成为 CNCF Sandbox 项目啦!- 锣鼓喧天、鞭炮齐鸣、红旗招展、忘词了。
开局两张图,内容全靠"编" 来,有图有真相! DevStream ️ CNCF DevStream joins CNCF Sandbox CNCF Cloud Native Int ...
- Vue路由的模块自动化与统一加载
首先呢,我们来看看一般项目路由是怎么划分的. 为什么这么划分呢?如果大项目业务非常多,单纯的单页面很难维护,我们只有这样规范化,才能高效率. 模块自动化与统一加载的好处: 规范化命名(模块名.业务名. ...
- DAST 黑盒漏洞扫描器 第六篇:运营篇(终)
0X01 前言 转载请标明来源:https://www.cnblogs.com/huim/ 当项目功能逐渐成熟,同时需要实现的是运营流程和指标体系建设.需要工程化的功能逐渐少了,剩下的主要工作转变成持 ...
- 手把手教你用 Python 下载手机小视频
今天为大家介绍使用 mitmproxy 这个抓包工具如何监控手机上网,并且通过抓包,把我们想要的数据下载下来. 启动 mitmproxy 首先我们通过执行命令 mitmweb 启动mitmproxy, ...
- C++ 练气期之二维数组与矩阵运算
1. 前言 C++中的一维数组可以存储线性结构的数据,二维数组可以存储平面结构的数据.如班上所有学生的各科目成绩就有二个维度,学生姓名维度和科目成绩维度. 这样的表格数据可以使用二维数组进行存储. 当 ...
- Tapdata 与星环 KunDB 完成产品兼容互认证
近日, Tapdata 实时数据即服务平台(Tapdata Real Time DaaS)与星环 KunDB 完成产品兼容互认证.经深圳钛铂数据有限公司和星环信息科技(上海)股份有限公司共同严格测 ...
- JavaWeb的技术体系
客户端和服务器端的交互 browser/ server(B/S)浏览器/服务器. client/server(C/S)应用/服务器.
- final关键字概念与四种用法和final关键字用于修饰类和成员方法
fifinal关键字 概述 学习了继承后,我们知道,子类可以在父类的基础上改写父类内容,比如,方法重写.那么我们能不能随意的继承 API中提供的类,改写其内容呢?显然这是不合适的.为了避免这种随意改写 ...