Golang 語言中怎麼提升 JSON 編解碼的性能?
大家好,我是 frank。
歡迎大家點擊上方藍色文字「Golang 語言開發棧」關注公衆號。
設爲星標,第一時間接收推送文章。
文末掃碼,大家一起學 Golang 語言。
01
介紹
在 Golang 語言中,我們一般會使用標準庫 encoding/json
序列化 / 反序列化 JSON,但是因爲 encoding/json
需要使用反射,所以如果在性能要求比較高的場景中,它就不太合適了。
本文我們要介紹的三方庫 easyjson
,它提供了快速且簡單的方式去序列化和反序列化 Golang 結構體 / JSON,官方文檔介紹,在性能測試中,easyjson
比標準庫 encoding/json
高 4~5 倍。
easyjson
的目標是保持生成的 Golang 代碼足夠簡單,以便它可以很容易地優化或修復,並且通過提供標準庫 encoding/json
中無法提供的選項,爲用戶提供自定義生成代碼的能力,例如生成 snake_case
名稱或默認啓用 omitempty
行爲。
02
安裝和生成代碼
在準備使用 easyjson
之前,我們需要先安裝 easyjson
。
安裝命令:
go get -u github.com/mailru/easyjson/...
安裝成功之後,我們就可以使用 easyjson
生成代碼了,也非常簡單,僅需運行以下命令。
生成代碼命令:
easyjson -all <file>.go
運行上面這條命令,會自動生成一個文件 <file>_easyjson.go
,文件中包含 <file>.go
文件中所有結構體對應的 marshaler 和 unmarshaler 方法。
需要注意的是,我們使用 easyjson
命令生成代碼之前,需要設置 GOPATH 環境變量。
如果我們使用 easyjson
命令生成代碼時,沒有指定 -all
選項,我們需要在需要生成相應代碼的結構體上方添加一個標籤 //easyjson:json
。
我們使用 easyjson -all <file>.go
生成代碼時,如果文件中個別結構體不需要生成相應代碼,我們可以在該結構體上方添加一個標籤 //easyjson:skip
。
除了 -all
選項,還有一些其他比較常用的選項,限於篇幅,我們不再贅述,感興趣的讀者朋友們可以查閱官方文檔瞭解更多。
03
使用示例
讀者朋友們閱讀完以上內容後,想必一定會動手操練一把,以下是本文的示例代碼,供讀者朋友們做個參考,完整代碼可以翻閱 GitHub。
結構體:
type User struct {
ID uint64 `json:"id"`
Name string `json:"name"`
}
序列化:
// 序列化
func encode() {
user := &model.User{
ID: 1,
Name: "lucy",
}
bs, err := user.MarshalJSON()
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("encode() type=%T\nbs=%v\nstr=%s\n", bs, bs, string(bs))
}
反序列化:
// 反序列化
func decode() {
user := new(model.User)
str := `{"id":1,"name":"lucy"}`
err := user.UnmarshalJSON([]byte(str))
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("decode() user=%+v\n", user)
}
04
總結
本文我們重點介紹了相比 Golang 標準庫 encoding/json
性能較高的三方庫 easyjson
,包括安裝、使用和示例代碼。感興趣的讀者朋友,可以 benchmark 做個對比。
讀到這裏,讀者朋友們可能會有個疑問,既然 easyjson
不會使用反射,爲什麼結構體定義時還使用 json
標籤,實際上,easyjson
在生成代碼時,也使用了反射。
在應用程序開發中,如果標準庫可以滿足需求,不建議引入三方庫,導致增加應用程序的維護成本。
參考資料:
https://github.com/mailru/easyjson
https://pkg.go.dev/encoding/json@go1.16.7
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/wkqk1cgYKWnbIsHqoTA5UA