[转载]Go JSON 技巧
时间:2022-05-04
本文章向大家介绍[转载]Go JSON 技巧,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
相对于很多的语言来说, Go 的 JSON 解析可谓简单至极. 问题 通常情况下, 我们在 Go 中经常这样进行 JSON 的解码:
package main
import "encoding/json"
// jsonText comes from http://json.org/example.html
var jsonText = []byte(`
{ "glossary":{
"title":"example glossary",
"GlossDiv":{
"title":"S",
"GlossList":{
"GlossEntry":{
"ID":"SGML",
"SortAs":"SGML",
"GlossTerm":"Standard Generalized Markup Language",
"Acronym":"SGML",
"Abbrev":"ISO 8879:1986",
"GlossDef":{
"para":"A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso":[
"GML",
"XML"
]
},
"GlossSee":"markup"
}
}
}
}
}`)
type glossary struct {
Glossary struct {
Title string `json:"title"`
GlossDiv struct {
Title string `json:"title"`
GlossList struct {
GlossEntry struct {
ID string `json:"ID"`
SortAs string `json:"SortAs"`
GlossTerm string `json:"GlossTerm"`
Acronym string `json:"Acronym"`
Abbrev string `json:"Abbrev"`
GlossDef struct {
Para string `json:"para"`
GlossSeeAlso []string `json:"GlossSeeAlso"`
} `json:"GlossDef"`
GlossSee string `json:"GlossSee"`
} `json:"GlossEntry"`
} `json:"GlossList"`
} `json:"GlossDiv"`
} `json:"glossary"`
}
func main() {
var g glossary
json.Unmarshal(jsonText, &g)
}
这样的解码对于我们日常使用好像也没什么问题, 起码能用 ? 对于一段 JSON, 我们解码的时候未必需要立即解码所有的部分, 什么意思呢 ?
拿上面的例子代码来说, 我们解码 jsonText , 可能仅需要马上使用 Title 和 GlossDiv.Title . 那么对于这种情况我们怎么做合适呢 ?
type glossarySectional struct {
Glossary struct {
Title string `json:"title"`
GlossDiv struct {
Title string `json:"title"`
GlossList json.RawMessage `json:"GlossList"` // diff: delay JSON decoding
} `json:"GlossDiv"`
} `json:"glossary"`
}
func main() {
var g glossarySectional
json.Unmarshal(jsonText, &g)
}
没错, 魔法就在 GlossList json.RawMessage . 我们看相关文档怎么说:
RawMessage is a raw encoded JSON value. It implements Marshaler and Unmarshaler and can be used to delay JSON decoding or precompute a JSON encoding.
一目了然, RawMessage 起到了延迟解码一个 JSON 值的作用. 那么你可能会说, 这有啥用呢 ?
这对于普通的解码可能问题不大, 但是对于一些像消息传递(Kafka 这种), 细微的延迟可能会造成很大的影响. 我们可以通过简单的 benchmark 测试一下这细微的差别:
// 其他代码略 ... 完整代码参见: http://bit.ly/2skxY9L .
func benchmarkJSONUnmarshal(f func(), b *testing.B) {
for n := 0; n < b.N; n++ {
f()
}
}func BenchmarkJSONUnmarshal_0(b *testing.B) {
benchmarkJSONUnmarshal(func() {
var g glossary
json.Unmarshal(jsonText, &g)
}, b)
}func BenchmarkJSONUnmarshal_1(b *testing.B) {
benchmarkJSONUnmarshal(func() {
var g glossarySectional
json.Unmarshal(jsonText, &g)
}, b)
}
我们通过运行 go test -run=NONE -bench=. ./... 可以得出(不同环境有略微差别):
BenchmarkJSONUnmarshal_0-8 200000 10565 ns/op
BenchmarkJSONUnmarshal_1-8 200000 7699 ns/op
差别幅度:
benchmark old ns/op new ns/op delta
BenchmarkJSONUnmarshal-8 10298 7591 -26.29%
可以看得出这个差别还是很大的, 特别是当 JSON 本身体量很大的时候.
结论 对于一些关乎性能的 JSON 解析的处理, 我们可以通过 json.RawMessage 进行性能的提升.
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Laravel5.7 数据库操作迁移的实现方法
- PHP7引入的"??"和"?:"的区别讲解
- Python自动化操作实现图例绘制
- ThinkPHP5.0框架使用build 自动生成模块操作示例
- PHP远程连接oracle数据库操作实现方法图文详解
- 微信公众平台开发教程②微信端分享功能图文详解
- 微信公众平台开发教程⑥ 微信开发集成类的使用图文详解
- keras分类之二分类实例(Cat and dog)
- 详解Python 循环嵌套
- PHP中quotemeta()函数的用法讲解
- 微信公众号实现扫码获取微信用户信息(网页授权)
- 实例说明js脚本语言和php脚本语言的区别
- 在Ubuntu 18.04上安装PHP 7.3 7.2和7.0的方法
- PHP7匿名类的用法示例
- laravel配置Redis多个库的实现方法