Golang 中使用 JSON 時如何區分空字段和未設置字段?
幾周前,我在使用 Golang 微服務,需要添加使用 JSON 數據的 CURP 操作的支持。通常,我會為實體創建一個結構體,該結構體中定義了所有字段以及 'omitempty' 屬性,如下所示

問題
但是這種表示形式帶來了嚴重的問題,尤其對于 Update 或 Edit 操作而言.
例如,假設更新請求的 JSON 數據看起來像是這樣

注意為空的 desc 字段。現在讓我們來看看這段請求數據在 Go 中解封后是怎么樣的

這里的描述是一個空字符串,很明顯客戶端希望將 desc 設置為空字符串,這是由我們的程序推斷出來的.
但是,如果客戶端不希望更改 Desc 的現有值,在這種情況下,再次發送一個描述字符串是不正確的,因此請求的 JSON 數據可能看起來像是這樣
{"id":"1234","name":"xyz"}
我們解封到我們的結構體中

額,仍然會將 Desc 作為空字符串獲取,那么如何區分未設置字段和空字段
簡答?指針
解決辦法
受到一些現有 Golang 庫的啟發,如?go-github. 我們可以將結構體字段更改為指針類型,如下所示

通過這樣做,我們在字段中添加了額外的狀態。如果原始 JSON 中不存在該字段,則結構體字段將為空 (*nil*).
另一方面,如果該字段確實存在并且為空,則指針不為空,并且該字段包含空值.
注意?- 我沒有將 'Id' 字段更改為指針類型,因為它不具備空狀態,id 是必需的,類似數據庫中的 id.
我們再嘗試一下.

Output

第一種情況,由于 desc 設置為空字符串,因此我們在?Desc?獲得了一個非空指針并包含一個空字符串的值。第二種情況,該字段未設置,我們得到了一個空字符串指針.
因此我們能夠區分兩種更新。這種方式不僅適用于字符串,而且適用于其他的所有數據類型,包括整型,嵌套結構體,等.
但是這種方法也存在一些問題.
空安全性: 非指針數據類型具備固有的空安全性。在 Golang 中這意味著字符串或整型永遠不能為空。他們始終具備默認值。但是如果定義了指針,則這些數據類型在未手動設置的情況下默認為空。因此,嘗試在不驗證可空性的情況下訪問那些指針的數據可能會導致應用程序崩潰.

通過始終檢查空指針可以很容易的解決此問題,但你的代碼可能會看起來會很啰嗦.
可打印性: 如在基于指針的解決方案的輸出中你可能已經注意到的問題,不會打印指針的值。二十打印了指針的十六進制值,這在應用程序中沒什么用。這也可以通過重新使用 stringer 接口來克服.

附錄:
-
解決上述問題的另一種方法是使用具有可為空類型的三方庫,其類型可提供檢查是否為空的方法,而無需關心指針.
原文地址:https://medium.com/@arpitkh96/differentiate-between-empty-and-not-set-fields-with-json-in-golang-957bb2c5c065
譯文地址:https://learnku.com/go/t/49332