上週末在台北講『Go 語言基礎課程』,其中一段介紹 Struct 的使用,發現有幾個學員對於在 Method 內要放 Pointer 或 Value 感到困惑,而我自己平時在寫 Go 語言也沒有注意到這點。好在強者學員 Dboy Liao 找到一篇說明:『Don’t Get Bitten by Pointer vs Non-Pointer Method Receivers in Golang』,在 Go 語言如何區分
func (s *MyStruct)
及 func (s MyStruct)
,底下我們先來看看簡單的 Struct 例子
package main import "fmt" type Cart struct { Name string Price int } func (c Cart) GetPrice() { fmt.Println(c.Price) } func main() { c := &Cart{"bage", 100} c.GetPrice() }上面是個很簡單的 Go struct 例子,假設我們需要動態更新 Price 值,可以新增
UpdatePrice
method。線上執行範例
package main import "fmt" type Cart struct { Name string Price int } func (c Cart) GetPrice() { fmt.Println("price:", c.Price) } func (c Cart) UpdatePrice(price int) { c.Price = price } func main() { c := &Cart{"bage", 100} c.GetPrice() c.UpdatePrice(200) c.GetPrice() }上面可以看到輸出的結果是 100,只用 value 傳值是無法改 Struce 內成員。我們可以用另外方式繞過。線上執行範例
package main import "fmt" type Cart struct { Name string Price int } func (c Cart) GetPrice() { fmt.Println("price:", c.Price) } func (c Cart) UpdatePrice(price int) *Cart { c.Price = price return &c } func main() { c := &Cart{"bage", 100} c.GetPrice() c = c.UpdatePrice(200) c.GetPrice() }從上面範例可以發現,將 struct 回傳,這樣就可以正確拿到修改的值。但是這解法不是我們想要的。來試試看用 Pointer 方式 線上執行範例
package main import "fmt" type Cart struct { Name string Price int } func (c Cart) GetPrice() { fmt.Println("price:", c.Price) } func (c Cart) UpdatePrice(price int) { fmt.Println("[value] Update Price to", price) c.Price = price } func (c *Cart) UpdatePricePointer(price int) { fmt.Println("[pointer] Update Price to", price) c.Price = price } func main() { c := &Cart{"bage", 100} c.GetPrice() c.UpdatePrice(200) fmt.Println(c) c.UpdatePricePointer(200) fmt.Println(c) }只要使用 pointer 方式傳值就可以正確將您需要改變的值寫入,所以這邊可以結論就是,如果只是要讀值,可以使用 Value 或 Pointer 方式,但是要寫入,則只能用 Pointer 方式。其實在 Go 語言官方有整理 FAQ,竟然之前都沒發現,參考底下官方給的建議。