四條原則完全搞懂值接收者和指針接收者

感性認識:函數

1、值類型接收者的方法 至關於 值類型的函數入參
2、指針類型接收者的方法 至關於 指針類型的函數入參優化

代碼演示:指針

package main

import "fmt"

func main() {
	c1 := Child{1} // c1變量保存的是值類型
	c1.Age() // 查看age
	fmt.Printf("%v", c1)
	c1.GrowUp() // 值類型調用者,指針類型接受者,age發生改變,實際(&c1).GrowUp()
	fmt.Printf("%v", c1)
	c1.TryGrowUp() // 值類型調用者,值類型接受者,age沒有改變
	fmt.Printf("%v", c1)

	fmt.Printf("\n-----------------------\n")

	c2 := &Child{1} // c2變量保存的是指針類型
	c2.Age() // 查看age
	fmt.Printf("%v", c2)
	c2.GrowUp() // 指針類型調用者,指針類型接受者,age發生改變
	fmt.Printf("%v", c2)
	c2.TryGrowUp() // 指針類型調用者,值類型接受者,age沒有改變,實際(*c2).TryGrowUp()
	fmt.Printf("%v", c2)

	fmt.Printf("\n-----------------------\n")

	var p1 People = &Child{1} // p1是一個接口,若將 &Child{1} 改成 Child{1} 則可經過編譯
	p1.Age()
	fmt.Printf("%v", p1)
	p1.GrowUp()
	fmt.Printf("%v", p1)
	c1.TryGrowUp()
	fmt.Printf("%v", p1)
}

type People interface {
	Age()
	GrowUp()
}

type Child struct {
	age int
}

func (c Child) Age() int {
	return c.age
}

func (c *Child) GrowUp() {
	c.age++
}

func (c Child) TryGrowUp() {
	c.age++
}

結果:code

{1}{2}{2}對象

&{1}&{2}{2}接口

cannot use &(Child literal) (value of type *Child) as People value in variable declaration: wrong type for method Agecompilerit

結論io

  1. 值接收者的方法不會修改調用者
  2. 指針接收者的方法會修改調用者
  3. 語言有語法糖對使用原始對象的調用者進行優化
  4. 當給接口傳遞的是指針,同時實現接口的對象方法中存在值接收者和指針接收者實現將不會經過編譯,理由是兩種接收者對數據的表現行爲不一致,簡單說既:指針類型可能會修改調用者,而值接收者不會
相關文章
相關標籤/搜索