"Завързани" методи

Казвали сме ви, че функциите са пълноправни обекти в езика. Също така сме ви казвали, че методи са обикновенни функции. Изхождайки от това би следвало, че можем да си направим промелива, чиято стойност е метод на някой обект. Нека си направим един тип, с който ще направим малка демонстрация на това:

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)

Пълния код на примерите може да бъде намерен тук.