JSON

Go语言中如何自动选择json解析库

字号+ 作者:H5之家 来源:H5之家 2017-11-08 11:05 我要评论( )

golang官方为我们提供了标准的json解析库 encoding/json ,大部分情况下,使用它已经够用了。不过这个解析包有个很大的问题性能。它不够快,如果我们开发高性能

> 脚本语言 > Golang >

Go语言中如何自动选择json解析库 2017-11-06 13:03 出处:清屏网 人气: 

golang官方为我们提供了标准的json解析库– encoding/json ,大部分情况下,使用它已经够用了。不过这个解析包有个很大的问题–性能。它不够快,如果我们开发高性能、高并发的网络服务就无法满足,这时就需要高性能的json解析库,目前性能比较高的有 json-iterator 和 easyjson 。

现在我们需要引进一个高性能的json解析库,这里以 json-iterator 为例,但是我们全部换掉又不放心,所以可以先小范围的测试下,这时候我们就需要两个解析库并存,那么这时候我们如何选择我们需要的解析库编译和运行呢?

解决上面问题的办法就是条件编译。做过C/C++开发的都了解它有预编译可以解决这个问题,那么对于Go是没有预编译的,但是Go语言为我们提供了基于tags的编译约束来解决这个问题。

统一JSON库

我们先举个例子看看结果。现在我们需要两个库并存,所以我们先得统一这两个库的用法(参考适配器模式),这里我们使用一个自定义的 json 包来适配 encoding/json 和 json-iterator 。

json/json.go

// +build !jsoniter package json import ( "encoding/json" "fmt" ) func MarshalIndent(vinterface{}, prefix, indentstring)([]byte, error) { fmt.Println("Use [encoding/json] package") return json.MarshalIndent(v,prefix,indent) }

json/jsoniter.go

// +build jsoniter package json import ( "fmt" "github.com/json-iterator/go" ) var ( json = jsoniter.ConfigCompatibleWithStandardLibrary ) func MarshalIndent(vinterface{}, prefix, indentstring)([]byte, error) { fmt.Println("Use [jsoniter] package") return json.MarshalIndent(v,prefix,indent) }

目录结构如下:

json ├── json.go └── jsoniter.go

例子中以 MarshalIndent 函数为例,我们发现 json 包下的两个go文件中都有 MarshalIndent 函数的定义,并且签名一致,但是它们又是使用不同的json解析库实现,这就是我们统一适配包装后的结果,调用统一了。

Demo演示

为了区分调用的是哪个json库的具体实现,我加了打印日志,以便区分。现在我们使用 json.MarshalIndent 测试一下。

package main import ( "fmt" "flysnow.org/hello/json" ) func main() { u:=user{"飞雪无情","","flysnow_org"} b,err:=json.MarshalIndent(u,""," ") if err!=nil { fmt.Println(err) } else { fmt.Println(string(b)) } } type user struct { Name string Blog string Wechat string }

使用很简单,把一个 user 结构体对象转为json字符串,并打印出来。我们运行 go run main.go 看看结果。

Use [encoding/json] package { "Name": "飞雪无情", "Blog": "", "Wechat": "flysnow_org" }

恩,很完美,保持我们默认使用 encoding/json 库的方式不变。现在我们换一种编译运行方式:

-> go run -tags=jsoniter main.go Use [jsoniter] package { "Name": "飞雪无情", "Blog": "", "Wechat": "flysnow_org" }

这次运行和上次不同的地方在于我们加了 -tags=jsoniter ,然后就使用了 json-iterator 这个json库,这就是选择性的条件编译,达到了我们小部分测试新的json库的目的。

如果我们不是运行,是编译构建的话,改为 go build -tags=jsoniter . 即可,即可生成使用 json-iterator 解析的可执行文件。

条件编译

我们发现,条件编译的关键在于 -tags=jsoniter ,也就是 -tags 这个标志,这就是Go语言为我们提供的条件编译的方式之一。

好了,回过头来看我们刚开始时 json/json.go 、 json/jsoniter.go 这两个Go文件的顶部,都有一行注释:

// +build !jsoniter // +build jsoniter

这两行是Go语言条件编译的关键。 +build 可以理解为条件编译tags的声明关键字,后面跟着tags的条件。

// +build !jsoniter 表示,tags不是 jsoniter 的时候编译这个Go文件。

// +build jsoniter 表示,tags是 jsoniter 的时候编译这个Go文件。

也就是说,这两种条件是互斥的,只有当 tags=jsoniter 的时候,才会使用 json-iterator ,其他情况使用 encoding/json 。

小结

利用条件编译,我们实现了灵活选择json解析库的目的,除此之外,有时间我再细讲,而且tags只是其中的一部分,Go语言还可以根据Go文件后缀进行条件编译。

 

分享给小伙伴们:

本文标签: Go语言,json/">Go语言,json

相关文章

发表评论愿您的每句评论,都能给大家的生活添色彩,带来共鸣,带来思索,带来快乐。

  • 本类最热新闻

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • go数据和json格式数据之间的转换

      go数据和json格式数据之间的转换

      2017-11-08 08:02

    • android开发实现天气情况的获取(Json来返回数据)

      android开发实现天气情况的获取(Json来返回数据)

      2017-11-07 12:00

    • php针对json操作:json

      php针对json操作:json

      2017-11-07 12:00

    • C++json解析库

      C++json解析库

      2017-11-06 13:06

    网友点评