Go-Methoden
Eine Methode ist eine Funktion mit einem Empfänger. Der Empfänger kann ein benutzerdefinierter Typ oder ein Basis-Typ sein.
Deklaration
Das Format der Methodendeklaration lautet wie folgt:
func (Empfänger) Methodenname(Parameter) Rückgabewert {
Methodenrumpf
}Beispiel:
type Person struct {
Name string
Age int
}
func (p Person) SayHello() {
fmt.Printf("Hallo, mein Name ist %s\n", p.Name)
}In diesem Beispiel ist Person der Empfängertyp und p der Empfänger. SayHello ist die Methodenname.
Wertempfänger vs. Zeigerempfänger
Es gibt zwei Arten von Empfängern: Wertempfänger und Zeigerempfänger.
Wertempfänger
Ein Wertempfänger erhält eine Kopie des Werts. Änderungen am Empfänger wirken sich nicht auf den ursprünglichen Wert aus.
type Person struct {
Name string
Age int
}
func (p Person) SetName(name string) {
p.Name = name
}
func main() {
p := Person{Name: "Alice", Age: 25}
p.SetName("Bob")
fmt.Println(p.Name) // Alice
}Zeigerempfänger
Ein Zeigerempfänger erhält einen Zeiger auf den Wert. Änderungen am Empfänger wirken sich auf den ursprünglichen Wert aus.
type Person struct {
Name string
Age int
}
func (p *Person) SetName(name string) {
p.Name = name
}
func main() {
p := Person{Name: "Alice", Age: 25}
p.SetName("Bob")
fmt.Println(p.Name) // Bob
}TIP
Wenn der Empfänger ein großer Strukturtyp ist, ist es effizienter, einen Zeigerempfänger zu verwenden, da keine Kopie erstellt werden muss.
Methodenaufruf
Methoden können auf Werte und Zeiger aufgerufen werden. Go konvertiert automatisch zwischen ihnen.
type Person struct {
Name string
Age int
}
func (p Person) SayHello() {
fmt.Printf("Hallo, mein Name ist %s\n", p.Name)
}
func (p *Person) SetAge(age int) {
p.Age = age
}
func main() {
p := Person{Name: "Alice", Age: 25}
p.SayHello() // &p wird automatisch verwendet
p.SetAge(26) // p wird automatisch verwendet
(&p).SayHello() // p wird automatisch verwendet
(&p).SetAge(27) // &p wird automatisch verwendet
}Methoden mit gleichem Namen
Methoden mit gleichem Namen können in verschiedenen Typen definiert werden.
type Dog struct{}
type Cat struct{}
func (d Dog) Speak() {
fmt.Println("Woof!")
}
func (c Cat) Speak() {
fmt.Println("Meow!")
}Methodenexport
Methoden können exportiert werden, indem der Methodenname mit einem Großbuchstaben beginnt.
type Person struct {
name string
}
func (p *Person) SetName(name string) {
p.name = name
}
func (p *Person) GetName() string {
return p.name
}In diesem Beispiel sind SetName und GetName exportierte Methoden, die von anderen Paketen aufgerufen werden können.
Methoden für Basis-Typen
Methoden können auch für Basis-Typen definiert werden.
type MyInt int
func (m MyInt) IsEven() bool {
return m%2 == 0
}
func main() {
n := MyInt(4)
fmt.Println(n.IsEven()) // true
}TIP
Methoden können nicht für nicht-benutzerdefinierte Typen definiert werden. Zum Beispiel können Sie keine Methode für int definieren.
Embedding
Wenn eine Struktur eine andere Struktur embeddet, werden die Methoden der eingebetteten Struktur auch für die äußere Struktur verfügbar.
type Animal struct{}
func (a Animal) Eat() {
fmt.Println("Essen")
}
type Dog struct {
Animal
}
func main() {
d := Dog{}
d.Eat() // Dog kann Animal.Eat aufrufen
}Methoden vs. Funktionen
Der Hauptunterschied zwischen Methoden und Funktionen ist, dass Methoden einen Empfänger haben. Methoden können auf Werte oder Zeiger aufgerufen werden, während Funktionen direkt aufgerufen werden.
// Funktion
func Add(a, b int) int {
return a + b
}
// Methode
type MyInt int
func (m MyInt) Add(n MyInt) MyInt {
return m + n
}