专栏首页飞雪无情的博客Go语言中自动选择json解析库

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

本文为原创文章,转载注明出处,欢迎扫码关注公众号flysnow_org或者网站http://www.flysnow.org/,第一时间看后续精彩文章。觉得好的话,顺手分享到朋友圈吧,感谢支持。

背景

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

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

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

统一JSON库

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

json/json.go

// +build !jsoniter

package json

import (
	"encoding/json"
	"fmt"
)

func MarshalIndent(v interface{}, prefix, indent string) ([]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(v interface{}, prefix, indent string) ([]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{"飞雪无情","http://www.flysnow.org/","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": "http://www.flysnow.org/",
  "Wechat": "flysnow_org"
}

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

-> go run -tags=jsoniter main.go

Use [jsoniter] package
{
  "Name": "飞雪无情",
  "Blog": "http://www.flysnow.org/",
  "Wechat": "flysnow_org"
}

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

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

条件编译

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

好了,回过头来看我们刚开始时json/json.gojson/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文件后缀进行条件编译。

本文为原创文章,转载注明出处,欢迎扫码关注公众号flysnow_org或者网站http://www.flysnow.org/,第一时间看后续精彩文章。觉得好的话,顺手分享到朋友圈吧,感谢支持。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Go语言实战笔记(二十五)| Go Struct Tag

    在上一篇介绍Go反射的时候,提到了如何通过反射获取Struct的Tag,这一篇文章主要就是介绍这个的使用和原理,在介绍之前我们先看一下JSON字符串和Struc...

    飞雪无情
  • Go语言经典库使用分析(三)| Gorilla Handlers 详细介绍

    在我们编写web服务端程序的时候,我们可能会对一些甚至全部的Http Request统一处理,比如我们记录每个访问的Request,对提交的Form表单进行映射...

    飞雪无情
  • 使用Nginx搭建PHP服务器

    一般我们都是采用Apache 作为PHP的解析服务器,这次则是采用Nginx这个强大的反向代理服务器来搭建PHP服务器。下面就以Linux发行版Ubuntu为例...

    飞雪无情
  • python json文件的使用

    json是一种轻量级数据交换格式,常用于http请求中,在日常运维工作中经常可以看到

    py3study
  • Python json 模块dumps、dump、loads、load的使用

    本文主要讲下json.dumps和json.dump、json.loads和json.load的区别,因为经常需要加载json文件,读取数据,傻傻分不清...

    用户1332428
  • 2018年7月23日数据存储到文件中的代码介绍:

    ******************************************************************

    武军超
  • Python json 模块dumps、dump、loads、load的使用

    本文主要讲下json.dumps和json.dump、json.loads和json.load的区别,因为经常需要加载json文件,读取数据,傻傻分不清...

    致Great
  • 干货 | 如何利用Python处理JSON格式的数据,建议收藏!!!

    JSON数据格式在我们的日常工作中经常会接触到,无论是做爬虫开发还是一般的数据分析处理,今天,小编就来分享一下当数据接口是JSON格式时,如何进行数据处理进行详...

    用户6888863
  • Flutter Notes |quicktype 解析 json 就是这么 easy~

    回想起 Android,从开始的 JsonArray、JsonObject,直到最后的 Gson,使用起来简直爽的嗨起~

    HLQ_Struggle
  • json字符串和字典的区别

    json字符串和字典的区别: json: (JavaScript Object Notation)的首字母缩写,字面的意思是(javascript对象表示法...

    武军超

扫码关注云+社区

领取腾讯云代金券