天天看点

Go语言 json分析

背景

Go语言自带的encode/json包提供了对JSON数据格式的编码和解码能力。解码JSON时encode/json包使用UnMarshall或者Decode方法根据开发者提供的存放解码后数据的变量的类型声明来解析JSON并把解码后的数据填充到Go变量里。所以解析JSON的关键其实是如何声明存放解析后数据的变量的类型。

Marshal函数执行流程

以下为 Go1.12 版本中 json.Marshal 函数的执行流程:

Go语言 json分析

在了解了 json.Marshal 函数的执行流程后,再来比较下在 Go1.10 和 Go1.12 版本中的 json.Marshal 函数在实现上有什么变化。通过之前的测试,可以发现从 Go1.10 至 Go1.12 版本中的 json.Marshal 函数的内存消耗上有了很大的改善。从源码的变化中可以发现在 Go1.12 版本中的 json.Marshal 函数添加了 encoder(编码器)的内存缓存:

Go语言 json分析

在使用了 sync.Pool 缓存 encoder 后,json.Marshal 函数极大地减少了内存分配操作。实际上 newEncodeState() 函数在 Go1.10 版本中就已经存在了,只不过没有被使用而已。

Unmarshal函数执行流程

以下为 Go1.12 版本中,json.Unmarshal 函数的执行流程:

Go语言 json分析

json.Unmarshal 函数同样使用 sync.Pool 缓存了 decoder。对于 json 序列化和反序列化而言,其性能瓶颈是迭代、反射 json 结构中每个字段。

参考资料

Go语言中文网微信公众号