Vraag golang - pas methode toe om te functioneren


Ik ben benieuwd of dit mogelijk is in Go. Ik heb een type met meerdere methoden. Is het mogelijk om een ​​functie te hebben die een methode gebruikt en deze voor het type kan noemen?

Hier is een klein voorbeeld van wat ik zou willen:

package main

import (
  "fmt"
)

type Foo int

func (f Foo) A() {
    fmt.Println("A")
}
func (f Foo) B() {
    fmt.Println("B")
}
func (f Foo) C() {
    fmt.Println("C")
}

func main() {
    var f Foo
    bar := func(foo func()) {
        f.foo()
    }
    bar(A)
    bar(B)
    bar(C)
}

Go denkt type Foo heeft een methode genaamd foo(), in plaats van het te vervangen door de doorgegeven methodaam.


10
2017-08-11 13:17


oorsprong


antwoorden:


Ja het is mogelijk. Je hebt 2 (3) opties:

Spec: Method-expressies

De uitdrukking Foo.A levert een functie op die gelijk is aan A maar met een expliciete ontvanger als eerste argument; het heeft een handtekening func(f Foo).

var f Foo
bar := func(m func(f Foo)) {
    m(f)
}
bar(Foo.A)
bar(Foo.B)
bar(Foo.C)

Hier is de methode-ontvanger expliciet. U geeft alleen de methode naam door (met het type waartoe het behoort) bar(), en als je dit belt, moet je de daadwerkelijke ontvanger doorgeven: m(f).

Output zoals verwacht (probeer het op de Ga speelplaats):

A
B
C

Spec: Methodewaarden

Als f is een waarde van het type Foo, de uitdrukking f.A levert een functiewaarde van het type op func() met impliciete ontvangerwaarde f.

var f Foo
bar := func(m func()) {
    m()
}
bar(f.A)
bar(f.B)
bar(f.C)

Merk op dat hier de methode-ontvanger impliciet is, deze wordt opgeslagen met de functiewaarde die wordt doorgegeven aan bar(), en zo wordt het genoemd zonder het expliciet op te geven: m().

Uitgang is hetzelfde (probeer het op de Ga speelplaats).

(Voor de volledigheid: reflectie)

Inferieur aan eerdere oplossingen (zowel in prestaties als in "veiligheid"), maar u kunt de naam van de methode doorgeven als een string waarde en gebruik vervolgens de reflect pakket om de methode met die naam te noemen. Het kan er als volgt uitzien:

var f Foo
bar := func(name string) {
    reflect.ValueOf(f).MethodByName(name).Call(nil)
}
bar("A")
bar("B")
bar("C")

Probeer dit op de Ga speelplaats.


22
2017-08-11 13:24