收錄於 《Go 基礎系列》,作者:瀟灑哥老苗。
學到什麼
什麼是方法?
如何呼叫方法?
什麼是值接收者和指標接收者?
如何使用 new 函式?
什麼是私有方法和公有方法?
概念
上篇學習了什麼是自定義型別,對於結構體也是自定義型別的一種,那方法是什麼?
如果一個函式屬於一個自定義型別時,那它被稱為方法,類似於物件導向中給類增加方法。
方法格式
在函式名前面寫上自己所屬的自定義型別後,這個函式就變為了該型別的方法。
type People ...
func (p *People) SetName(name string) string {
// ...
}
第一行自定義了一個型別,名為
People
。p *People
確定了SetName
函式屬於*People
型別,p
為型別的別名,也稱為接收者。p
類似面嚮物件語言中的this
,People
類似”class 類“。如果攜帶方法,自定義的型別不能為介面型別(
interface{}
)和 指標。
注:*People
前面的“星號”確定了接收者為指標型別,稱為指標接收者,下面會講。
方法名稱
方法的名稱在型別的所有方法名稱和所有欄位名稱中必須是唯一的。就算相同的名稱一個是欄位一個是方法名也是不可以的。
type People struct {
Name string
}
func (p People) Name() string {
return p.Name
}
以上程式碼錯誤,名稱不唯一。
如果方法名稱和型別名稱相同是可以允許的。
方法呼叫
不管自定義的型別是基於內建型別還是結構體,都可以攜帶方法。
// 內建型別
type Num int
func (n Num) String() string {
return fmt.Sprintf("%d", n)
}
// 結構體
type People struct {
Name string
Age int
}
func (p People) GetName() string {
return p.Name
}
以上程式碼中定義了兩個型別,每個型別分別攜帶了一個方法。
下來如何呼叫這兩個方法:
var n Num
n.String()
var p Peple
p.GetName()
先初始化好型別,然後再用“點”符號呼叫。
值接受者和指標接收者
1. 定義
在上面的程式碼中,是否注意到接收者型別有兩種,一種是帶星號(*People),一種是不帶的(People 和 Num)。
總結為:
帶星號的稱為:指標接收者。
不帶星號的稱為:值接收者。
還有一種特殊情況就是自定義的型別本身就是引用型別,就算接收者型別宣告中帶不帶”星號“它也屬於指標接收者。
type M map[string]string
func (m M) SetKey(key, val string) {
(m)[key] = val
}
因為 M
型別依賴的是 map
型別,map
本身就是一個引用型別,因此 m
為指標接收者。
2. 區別
如果方法是值接收者,執行方法時接收者會被複製一份,即使方法修改了接收者的值也不是原來的一份。
func (p People) SetName(name string) string {
p.Name = name
return name
}
初始化 People
修改 Name
欄位。
p1 := People{Name: "苗"}
p1.SetName("瀟灑哥")
fmt.Println(p1.Name)
// 輸出
苗
發現了沒,雖然呼叫了方法進行了修改,但還是不生效。因為 p1
和接收者 p
已經不是一個值了。如果想修改生效,只需把值接收者改為指標接收者。
func (p *People) SetName(name string) string {
p.Name = name
return name
}
3. 呼叫時型別轉化
在呼叫方法時,不管是值接收者還是指標接收者,呼叫時的變數型別是否是指標是不影響的。
例如:People
結構體的方法 SetName
不管是指標還是值接收者,以下程式碼都可以呼叫。
// 值
p1 := People{}
p1.SetName()
// 指標
p2 := &People{}
p2.SetName()
至於為什麼?當編譯器發現你呼叫的變數( p1 和 p2 )型別和接收者的型別不相同時,也就是一個是指標一個不是,這個時候就會自動轉化。
至於接收者的值被方法修改時結果會不會改變,和呼叫變數的型別沒關係。
New 函式使用
當初始化一個指標變數時,可以使用 “&” 符號,也可以使用 new 函式。
new(T)
例如,將 p2 := &People{}
修改。
p2 := new(People)
p2.Name = "老苗"
new(People)
和 &People{}
等價。
私有和公有
方法名大寫字母開頭公有,小寫字母開頭私有。如果方法所在的包和呼叫者不是同一個,那私有方法是不能被呼叫的,只能呼叫公有方法。
私有方法只能在同一個包內被呼叫。
總結
本篇文章完了之後,自定義型別和結構體的知識點就講完了,如果看到了這就給自己點個贊,堅持住!!!
本作品採用《CC 協議》,轉載必須註明作者和本文連結