flysnow_org

背景

encoding/jsonjson-iteratoreasyjson
json-iterator

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

统一JSON库

jsonencoding/jsonjson-iterator

json/json.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// +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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// +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)
}

目录结构如下:

1
2
3
json
├── json.go
└── jsoniter.go
MarshalIndentjsonMarshalIndent

Demo演示

json.MarshalIndent
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
}
usergo run main.go
1
2
3
4
5
6
Use [encoding/json] package
{
  "Name": "飞雪无情",
  "Blog": "http://www.flysnow.org/",
  "Wechat": "flysnow_org"
}
encoding/json
1
2
3
4
5
6
7
8
-> go run -tags=jsoniter main.go

Use [jsoniter] package
{
  "Name": "飞雪无情",
  "Blog": "http://www.flysnow.org/",
  "Wechat": "flysnow_org"
}
-tags=jsoniterjson-iterator
go build -tags=jsoniter .json-iterator

条件编译

-tags=jsoniter-tags
json/json.gojson/jsoniter.go
1
2
3
// +build !jsoniter

// +build jsoniter
+build
// +build !jsoniterjsoniter// +build jsoniterjsoniter
tags=jsoniterjson-iteratorencoding/json

小结

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

flysnow_org

扫码关注