首先,本篇不是爲了講值接收和指針接收的概念,因爲概念本身很好理解,不過爲了後面的驗證還是先寫一個例子,簡單說明一下。
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
如果結構體實現了接口,那麼:
如果結構體的方法中有接收指針的,接口賦值時必須是結構體指針;
如果結構體的方法都是接收值的,接口可以賦值爲結構體值,也可以賦值爲結構體指針。