go 結構體方法的值接收與指針接收

首先,本篇不是爲了講值接收和指針接收的概念,因爲概念本身很好理解,不過爲了後面的驗證還是先寫一個例子,簡單說明一下。

type treeNode struct {
	value int
	left, right *treeNode
}

func (node *treeNode) setValue(val int) {
	node.value = val
}

func (node treeNode) getValue() int{
	return node.value
}

例子很簡單,定義了一個樹節點的結構體,給出了一個設置樹節點值的方法,和一個獲取樹節點值的方法。

顯然,setValue是指針接收,getValue是值接收。

作爲一個初學者,我想搞清楚的是,指針接收者可以接收值嗎?值接收者又可以接收指針嗎?

想搞清楚這個問題,最好的辦法就是自己驗證,兩個問題,一個一個說。

指針接收者是否可以接收值?

首先,指針接收者接收指針肯定是沒有問題的。

func main()  {
	root := new(treeNode)
	root.setValue(1)
	fmt.Println(root.value)
}

結果:

改成接收值,再試一次。

func main()  {
	//root := new(treeNode)
	root := treeNode{0, nil, nil}
	root.setValue(1)
	fmt.Println(root.value)
}

結果:

也是沒有問題的,也就是說,指針接收者即使接收的是值,也會先將其轉化爲對應的指針,再做處理。

值接收者是否可以接收指針?

同樣的思路,首先,值接收者接收值肯定是沒問題的。

func main()  {
	root := treeNode{0, nil, nil}
	fmt.Println(root.getValue())
}

結果:

改成接收指針,再試一次。

func main()  {
	root := new(treeNode)
	fmt.Println(root.getValue())
}

結果:

也是沒有問題的,也就是說,值接收者即使接收到指針,也會先取出值,再做處理。

結論1

值/指針接收者均可以接收指針/值。

爲什麼是結論1?因爲到這裏還沒完,上面我們只是定義了結構體,並沒有用這個結構體實現接口。

如果是接口的話,條件並沒有這麼寬鬆。

當結構體用於實現接口

我們首先寫一個接口。

type Stack interface {
	Push(val int)
	Pop() int
}

然後定義一個結構體,並且定義Stack接口的兩個方法。

type Mystack []int

func (stack *Mystack) Pop() int {
	tail := (*stack)[len(*stack)-1]
	*stack = (*stack)[:len(*stack)-1]
	return tail
}

func (stack *Mystack) Push(val int) {
	*stack = append(*stack, val)
}

 這樣,Mystack結構體就實現了Stack接口。接下來用一下試試。

先把接口賦值爲結構體指針。

func main()  {
	var stack Stack
	stack = &mystack.Mystack{1}
	fmt.Println(stack)
	stack.Push(4)
	fmt.Println(stack)
	stack.Pop()
	fmt.Println(stack)
}

結果:

這個沒有問題,那再試試賦值結構體值。

結果,還沒運行goland就報錯了:

這意思就是,Mystack這個結構體的Push方法是接收指針的,賦值成值是不行的。由此觀之,當結構體方法接收指針時,接口也必須賦值爲結構體指針。

接下來我又把Mystack的兩個方法改成了接收值類型,然後接口也賦值爲值。

func (stack Mystack) Pop() int {
	tail := stack[len(stack)-1]
	stack = stack[:len(stack)-1]
	return tail
}

func (stack Mystack) Push(val int) {
	stack = append(stack, val)
}
stack = mystack.Mystack{1}

 這時候編譯運行就沒有問題了,結果如下:

那麼問題又來了,當結構體的方法都是接收值時,接口能不能賦值爲指針呢?

修改代碼:

stack = &mystack.Mystack{1}

然後再運行,結果如下:

看來是歐克的,下面總結一下。

結論2

如果結構體實現了接口,那麼:

如果結構體的方法中有接收指針的,接口賦值時必須是結構體指針;

如果結構體的方法都是接收值的,接口可以賦值爲結構體值,也可以賦值爲結構體指針。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章