Golang 中 Struct 內型別用指針和值的差異和時機
用範例說明 Struct 中型別用指針和值的差異和時機
之前一直有個疑問「Struct 定義的時候,Type 什麼時候要傳值?什麼時候傳址?」
網路上看了許多不同專案似乎都有不同的做法,直到最近遇到的問題讓我有了一點想法
在專案中我們常常先定義 Request 傳入的 Struct
再利用json.Unmarshal
將傳入的 json 轉換成 Struct,以利後續的操作
以前的 Struct 欄位需要的的預設值都是 false 所以 Type 都是直接傳值
這次的情境是遇到一個欄位預設值 是 true 就出意外了
直接用先看程式碼和執行結果
package main
import (
"encoding/json"
"fmt"
)
type John struct {
Name string `json:"name"`
CanRun bool `json:"canRun"`
CanFly bool `json:"canFly"`
}
type Doe struct {
Name string `json:"name"`
CanRun *bool `json:"canRun"`
CanFly *bool `json:"canFly"`
}
func main() {
var param = []byte(`{"Name":"John Doe", "canRun":true}`)
defult := true
var john = new(John)
json.Unmarshal(param, &john)
jsondata, _ := json.Marshal(john)
fmt.Println(string(jsondata))
var doe = new(Doe)
json.Unmarshal(param, &doe)
doejsondata, _ := json.Marshal(doe)
fmt.Println(string(doejsondata))
if doe.CanFly == nil {
doe.CanFly = &defult
}
doejsondata, _ = json.Marshal(doe)
fmt.Println(string(doejsondata))
}
在範例中有兩個 Struct
分別是 Type 為布林傳值的 John 和 Type 為布林指標的 Doe
若CanFly
這個欄位是「可選的」,並且預設值是「true」
範例程式碼中的param
模擬當使用者沒有傳入資料時的 Request
- 分別指派型別為 John 和 Doe 的變數
- 使用
json.Unmarshal
將傳入的 json 字串轉成 Struct - 透過
json.Marshal
轉成 json 字串方便閱讀並列印在畫面上
輸出結果第一行是在結構體中 Type 使用布林值的 John
當new(John)
的時候會自動帶入所謂的 zero value
,布林的預設 zero value 是 false
而Name
和CanRnu
都因為有傳入的關係,所以 zero value 被覆寫了
但是因為CanFly
是選填,而使用者未傳入所以依然是 false
我們無法在後續程式中判斷究竟是 user 傳入 false 還是那是 zero value
若是在 Struct 中使用「指針」做為型別,則可以看到輸出結果第二行CanFly
是 null
如此就可以在後續使用條件判斷式將預設值設定成「true」
這就是這次學習到在將 json 字串轉換成 Struct 時會遇到的預設值問題,以及如何用指標來解決這個問題