JSON解析

内置的json解析

主要通过FiledTag 来标识json的key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
type UserInfo struct {
Name string `json:"name"`
Age int `json:"age"`
Likes []string `json:"likes"`
}

func TestJson(t *testing.T) {
u := UserInfo{Name:"张三",Age: 10}
like := make([]string,0,2)
like = append(like,"看书")
like = append(like,"打球")
u.Likes = like
t.Log("<====================>")
//序列化
js, _err := json.Marshal(u)
if(_err == nil){
t.Logf("JSON format: %s",js)
}else{
t.Log(_err)
}
u2 := new(UserInfo)
//反序列化
json.Unmarshal([]byte(js),u2)
t.Log("====")
t.Log(u2)
}

  • 通过FiledTag 来定义json的key
  • json.Marshal 执行序列化操作
  • json.Unmarshal 执行反序列化操作

EasyJson 非反射的方式解析json

easyjson是一个json的第三方库。

地址 https://pkg.go.dev/github.com/mailru/easyjson

安装

1
2
3
4
5
6
7
8
# for Go 版本 < 1.17
go get -u github.com/mailru/easyjson/...



# for Go 版本 >= 1.17
go get github.com/mailru/easyjson && go install github.com/mailru/easyjson/...@latest

创建一个保存struct的go文件

1
2
3
4
5
6
7
8
9
10
11
12
package go_json

type Student struct {
UserName string `json:"user_name"`
Age int `json:"age"`
}


type Employee struct {
Id int `json:"id"`
Name string `json:"name"`
}

使用 easyjson 为指定的文件中的struct 对象生成json相关的方法。

1
2
//为某个文件中的结构文件生成
easyjson -all xxx.go
1
2
easyjson -all go_struct.go

执行完毕后,将生成一个 go_struct_easyjson.go 文件,原结构文件是 go_struct.go
此文件中定义了生成json 和解析json的相关代码。

测试和使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package go_json

import (
"fmt"
"testing"
)

func TestJson(t *testing.T) {
stu := Student{UserName:"张三",Age: 10}
//json序列化
bt,_ := stu.MarshalJSON()
fmt.Println(string(bt))

//json反序列化
jsonStr := "{\"id\":1,\"name\":\"束带结发\"}"


emp := Employee{}
emp.UnmarshalJSON([]byte(jsonStr))

fmt.Println(emp)
}

  • MarshalJSON() 生成json字符串,获取的是byte[]
  • UnmarshalJSON() 由一个json字符串解析到对象,如果json有错误,那么也不会报错只会没有相关的值信息。

测试

benchmark

基准测试(benchmark)是 go testing 库提供的,用来度量程序性能,算法优劣的利器。

指定一个时间(默认是1秒),看测试对象在达到时间上限时,最多能被执行多少次和在此期间测试对象内存分配情况。

实例测试一段代码的性能

1
2
3
4
5
6
7
8
9
10
11
12

//Benchmark + 名字
func BenchmarkTestFor(b *testing.B) {
b.StartTimer()
d := 10
for i := 0; i < b.N; i++ {
d += i
}
b.Logf("最终的结果 %d \n",d)
b.StopTimer()
}

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
goos: windows
goarch: amd64
pkg: test
cpu: Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz
BenchmarkName
hello_test.go:23: 最终的结果 10
hello_test.go:23: 最终的结果 4960
hello_test.go:23: 最终的结果 49995010
hello_test.go:23: 最终的结果 499999500010
hello_test.go:23: 最终的结果 4999999950000010
hello_test.go:23: 最终的结果 499999999500000010
BenchmarkName-4 1000000000 0.5937 ns/op
PASS

看一看到循环的N 是一个可变的数,通过不断加到b.N 的值测试程序运行的时间.

主要注意的是:

  • 函数必须以Benchmark开头
  • 测试函数必须接受一个指向Benchmark类型的指针作为唯一参数
  • 测试函数不能有返回值
  • 被测试的代码要放到循环里

使用命令执行

1
>go test -bench=TestFor

执行特定的测试

1
>go test -bench=.

执行当前目录下所有的