Byte Ebi's Logo

Byte Ebi 🍤

每天一小口,蝦米變鯨魚

Golang 中 Struct 內型別用指針和值的差異和時機

用範例說明 Struct 中型別用指針和值的差異和時機

Ray

之前一直有個疑問「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))
}

result

在範例中有兩個 Struct
分別是 Type 為布林傳值的 John 和 Type 為布林指標的 Doe

CanFly這個欄位是「可選的」,並且預設值是「true
範例程式碼中的param模擬當使用者沒有傳入資料時的 Request

  1. 分別指派型別為 John 和 Doe 的變數
  2. 使用json.Unmarshal將傳入的 json 字串轉成 Struct
  3. 透過json.Marshal轉成 json 字串方便閱讀並列印在畫面上

輸出結果第一行是在結構體中 Type 使用布林值的 John
new(John)的時候會自動帶入所謂的 zero value ,布林的預設 zero value 是 false
NameCanRnu都因為有傳入的關係,所以 zero value 被覆寫了
但是因為CanFly是選填,而使用者未傳入所以依然是 false
我們無法在後續程式中判斷究竟是 user 傳入 false 還是那是 zero value

若是在 Struct 中使用「指針」做為型別,則可以看到輸出結果第二行CanFlynull
如此就可以在後續使用條件判斷式將預設值設定成「true

這就是這次學習到在將 json 字串轉換成 Struct 時會遇到的預設值問題,以及如何用指標來解決這個問題

最新文章

Category

Tag