跳至主要内容

[Golang] 資料型別 Data Types

Value vs Reference Types

⚠️ 在 Go 中雖然都是 pass by value,但要不要使用 Pointer 端看該變數的型別,某些型別會表現得類似 pass by reference(Reference Types),例如 slice,這時候就可以不用使用 Pointer 即可修改原變數的值。

  • 為什麼有些型別會表現的類似 pass by reference 可以參考「Array and Slice」的內容。
  • Non-Pointer Values:string, int, float, boolean, array, struct
  • Pointer Wrapper Values: slice, map, function

在 Golang 中,雖然所有資料結構都是 Pass by value,但當碰到 slices、maps、functions 時,雖然它還是會 copy 一份新的,但實際上,它 copy 的是一個 pointer,所以即使它依然是 copy by value,但對這個變數進行修改時,會修改到 pointer 背後實際所指稱到的記憶體位址,進而使得在操作這些資料結構時,會感覺像是 Pass by Reference:

func updateMenu(y map[string]float64) {
// y 一樣會時 copy 一個新的變數,但它是 pointer
// 實際上會指稱到背後相同的記憶體位址
y["cake"] = 2.99
}

func main() {
menu := map[string]float64{
"apple": 5.95,
"banana": 3.99,
}

updateMenu(menu)
fmt.Println(menu) // map[apple:5.95 banana:3.99 cake:2.99]
}

Imgur

Concrete vs Interface Type

  • concrete type 指的是可以被賦值的型別,例如,map, struct, int, string、一些自訂的 type。
  • interface type 無法直接賦值的型別

Zero values

Zero values @ A Tour of Gp

在 GO 中,如果宣告了某個變數但沒有賦值的話,會使用 zero value

Data TypeZero Value
int0
float640
boolfalse
String""

型別轉換(Type Conversion)

T(v) 這種方式,可以把 v 的值轉換成 T 這個型別。舉例來說:

func main() {
i := 42 // int
f := float64(i) // int 轉成 float64
u := uint(f) // float 64 轉成 uint

fmt.Println(i, f, u)
}

golang

func main() {
hello := "Hello World"
helloSlice := string2ByteSlice(hello)
fmt.Println(helloSlice)

helloString := byteSlice2String(helloSlice)
fmt.Println(helloString)
}

// byte slice 轉成 string
func byteSlice2String(b []byte) string {
return string(b)
}

// string 轉成 byte slice
func string2ByteSlice(s string) []byte {
return []byte(s)
}

自定義資料型別

// 定義 cards 這個型別,它的本質是 slice of strings
type cards []string

// 定義 person 這個型別,它的本質是 struct
type person struct {
firstName string
lastName string
}

透過 function receiver 為該 type 添加方法

我們可以針對自定義的 data type 透過 function receiver 去建立方法,可以參考「[Golang] 函式 function」中的內容。

參考