類型的值也可以調(diào)用指針接收者的方法!
學(xué)習(xí)golang中關(guān)于方法部分知識的人一定了解過方法集(Method Set)
的概念圈澈,也一定對上面這張圖不陌生,方法集定義如下規(guī)則:
規(guī)則:
類型的值的方法集只包含值接收者聲明的方法
指向 T 類型的指針的方法集既包含值接收者聲明的方法尘惧,也包含指針接收者聲明的方法
實際使用過程中會發(fā)現(xiàn)康栈,在T的值可尋址的情況下,類型的值也可以調(diào)用指針接收者的方法
package main
import "fmt"
type baseImpl string
const (
BI = baseImpl("1234")
)
type base interface {
func1 ()
}
func (b *baseImpl) func1() {
fmt.Println("invoke base impl func1")
}
func main() {
bi := baseImpl("1234")
bi.func1() // 正常執(zhí)行褥伴,輸出 "invoke base impl func1"
BI.func1() // 編譯器報錯谅将,Cannot call a pointer method on 'BI'
}
上述代碼中,定義了一個接口 base
以及其實現(xiàn)類 baseImpl
重慢,并且baseImpl
是通過指針接收者的形式來實現(xiàn)接口定義的方法
在實際使用過程中可以看到饥臂,定義baseImpl
的值bi
是可以調(diào)用func1
方法的,因為bi
是可以尋址的
但是似踱,由于常量BI
是不可尋址的隅熙,所以它遵循規(guī)則稽煤,無法調(diào)用func1
方法
由此可見,對于可尋址的值而言囚戚,其方法集的范圍包含了接收者類型為值類型和指針類型酵熙;對于不可尋址的值而言,其方法集的范圍僅包含值類型接收者
什么值是不可尋址的驰坊?
常見不可尋址的值的類型有:
- 常量
- 基本類型值
- 運算結(jié)果值
- 字符串索引表達(dá)式和切片表達(dá)式的結(jié)果值
- 字典的索引表達(dá)式結(jié)果值
- 函數(shù)匾二、方法,及其調(diào)用表達(dá)式
- 類型轉(zhuǎn)換
- 斷言
package main
const (
I = 1
)
func main() {
i := &I // 常量不可尋址
str := &"1234" // 基本類型拳芙,不可尋址
u := &str[0] // 字符串索引表達(dá)式察藐,不可尋址
s := &str[1:2] // 字符串切片表達(dá)式,不可尋址
i2 := &int64(123) // 類型強(qiáng)轉(zhuǎn)舟扎,不可尋址
strArr := []string{""}
sa := &strArr[0] // 切片的索引表達(dá)式是可尋址的
}
總的來看分飞,不可變的、臨時結(jié)果睹限、以及不安全的譬猫,都不可尋址
- 不可變的:如常量
- 臨時結(jié)果:如運算結(jié)果值,索引表達(dá)式羡疗,切片表達(dá)式(切片的索引表達(dá)式除外)等
- 不安全的:如字典索引表達(dá)式染服,函數(shù),方法等
方法接收者應(yīng)該選擇值類型還是指針類型顺囊?
應(yīng)該選擇指針類型接收者肌索,原因:
- 使用指針接收者意味著支持修改接收者指向的值
- 避免方法調(diào)用時,由值復(fù)制帶來的內(nèi)存&性能問題