背景
Go語言自帶的encode/json包提供了對JSON資料格式的編碼和解碼能力。解碼JSON時encode/json包使用UnMarshall或者Decode方法根據開發者提供的存放解碼後資料的變量的類型聲明來解析JSON并把解碼後的資料填充到Go變量裡。是以解析JSON的關鍵其實是如何聲明存放解析後資料的變量的類型。
Marshal函數執行流程
以下為 Go1.12 版本中 json.Marshal 函數的執行流程:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiclRnblN2XjlGcjAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHLxEFRNdXQU50dRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL1czM3UDOwATMzITNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
在了解了 json.Marshal 函數的執行流程後,再來比較下在 Go1.10 和 Go1.12 版本中的 json.Marshal 函數在實作上有什麼變化。通過之前的測試,可以發現從 Go1.10 至 Go1.12 版本中的 json.Marshal 函數的記憶體消耗上有了很大的改善。從源碼的變化中可以發現在 Go1.12 版本中的 json.Marshal 函數添加了 encoder(編碼器)的記憶體緩存:
在使用了 sync.Pool 緩存 encoder 後,json.Marshal 函數極大地減少了記憶體配置設定操作。實際上 newEncodeState() 函數在 Go1.10 版本中就已經存在了,隻不過沒有被使用而已。
Unmarshal函數執行流程
以下為 Go1.12 版本中,json.Unmarshal 函數的執行流程:
json.Unmarshal 函數同樣使用 sync.Pool 緩存了 decoder。對于 json 序列化和反序列化而言,其性能瓶頸是疊代、反射 json 結構中每個字段。
參考資料
Go語言中文網微信公衆号