"Завързани" методи
Казвали сме ви, че функциите са пълноправни обекти в езика. Също така сме ви казвали, че методи са обикновенни функции. Изхождайки от това би следвало, че можем да си направим промелива, чиято стойност е метод на някой обект. Нека си направим един тип, с който ще направим малка демонстрация на това:
type greeter struct {
Name string
}
func (g *greeter) SayHi(name string) {
fmt.Printf("Hi, %s! I am %s (%p)\n", name, g.Name, g)
}
Сега спокойно можем да си създадем нов обект от този тип
var p = &greeter{Name: p}
Ако всичко което сме казали до сега е вярно, бихме могли да направим следното:
pGreeter := p.SayHi
Какво точно е pGreeter
? Това е функция, с един аргумент (name string
), която е "завързана" за p
. Когато я извикаме, на практика все едно викаме p.SayHi
:
fmt.Printf("Calling p.SayHi:\n")
p.SayHi("Pesho")
fmt.Printf("Calling pGreeter:\n")
pGreeter("Pesho")
Изход от горното парче код ще е нещо като
Calling p.SayHi:
Hi, Pesho! I am p (0x1040a130)
Calling pGreeter:
Hi, Pesho! I am p (0x1040a130)
До тук добре! Но има още. Нека разгледаме това:
unboundGreeter := (*greeter).SayHi
Какво пък ще е това? Можем да го наречен "развързан" метод. Той вече е различен вид функция от pGreeter
. unboundGreeter
вече взима два аргумента: pointer receiver и стринг.
unboundGreeter(p, "Gosho")
unboundGreeter(&greeter{Name: "other"}, "Maria")
Това би извело нещо като
Hi, Gosho! I am p (0x1040a130)
Hi, Maria! I am other (0x1040a170)
Пълния код на примерите може да бъде намерен тук.