Go
Objekt orientierte Programmierung
Suche…
Bemerkungen
Die Schnittstelle kann nicht mit Zeigerempfängern implementiert werden, da *User
kein User
Structs
Go unterstützt benutzerdefinierte Typen in Form von Strukturen und Typ-Aliasnamen. structs sind zusammengesetzte Typen, die Komponententeile, aus denen der Strukturtyp besteht, werden Felder genannt . Ein Feld hat einen Typ und einen Namen, die einmalig sein müssen.
package main
type User struct {
ID uint64
FullName string
Email string
}
func main() {
user := User{
1,
"Zelalem Mekonen",
"[email protected]",
}
fmt.Println(user) // {1 Zelalem Mekonen [email protected]}
}
Dies ist auch eine gesetzliche Syntax zur Definition von Strukturen
type User struct {
ID uint64
FullName, Email string
}
user := new(User)
user.ID = 1
user.FullName = "Zelalem Mekonen"
user.Email = "[email protected]"
Eingebettete Strukturen
Da eine Struktur auch ein Datentyp ist, kann sie als anonymes Feld verwendet werden. Die äußere Struktur kann direkt auf die Felder der eingebetteten Struktur zugreifen, selbst wenn die Struktur aus einem anderen Paket stammt. Dieses Verhalten bietet eine Möglichkeit, einige oder alle Ihrer Implementierung von einem anderen Typ oder einer Gruppe von Typen abzuleiten.
package main
type Admin struct {
Username, Password string
}
type User struct {
ID uint64
FullName, Email string
Admin // embedded struct
}
func main() {
admin := Admin{
"zola",
"supersecretpassword",
}
user := User{
1,
"Zelalem Mekonen",
"[email protected]",
admin,
}
fmt.Println(admin) // {zola supersecretpassword}
fmt.Println(user) // {1 Zelalem Mekonen [email protected] {zola supersecretpassword}}
fmt.Println(user.Username) // zola
fmt.Println(user.Password) // supersecretpassword
}
Methoden
In Go ist eine Methode
eine Funktion, die auf eine Variable eines bestimmten Typs wirkt, der als Empfänger bezeichnet wird
Der Empfänger kann alles sein, nicht nur structs
sondern sogar eine function
. Alias-Typen für integrierte Typen wie int
, string
und bool
können eine Methode haben. Eine Ausnahme von dieser Regel besteht darin, dass interfaces
( structs
) keine Methoden haben können, da eine Schnittstelle ist eine abstrakte Definition und eine Methode ist eine Implementierung, bei der versucht wird, einen Kompilierungsfehler zu generieren.
Durch das Kombinieren von structs
und methods
Sie eine genaue Entsprechung einer class
in der objektorientierten Programmierung.
Eine Methode in Go hat die folgende Signatur
func (name receiverType) methodName(paramterList) (returnList) {}
package main
type Admin struct {
Username, Password string
}
func (admin Admin) Delete() {
fmt.Println("Admin Deleted")
}
type User struct {
ID uint64
FullName, Email string
Admin
}
func (user User) SendEmail(email string) {
fmt.Printf("Email sent to: %s\n", user.Email)
}
func main() {
admin := Admin{
"zola",
"supersecretpassword",
}
user := User{
1,
"Zelalem Mekonen",
"[email protected]",
admin,
}
user.SendEmail("Hello") // Email sent to: [email protected]
admin.Delete() // Admin Deleted
}
Pointer Vs Wertempfänger
Der Empfänger einer Methode ist aus Leistungsgründen normalerweise ein Zeiger, da wir keine Kopie der Instanz erstellen würden, wie dies beim Wertempfänger der Fall wäre. Dies gilt insbesondere, wenn der Empfängertyp eine Struktur ist. Ein anderer Grund, aus dem Empfängertyp einen Zeiger zu machen, wäre so, dass wir die Daten ändern könnten, auf die der Empfänger zeigt.
Ein Wertempfänger wird verwendet, um eine Änderung der Daten zu vermeiden, die der Empfänger enthält. Ein vaule-Empfänger kann einen Performance-Treffer verursachen, wenn der Empfänger eine große Struktur hat.
package main
type User struct {
ID uint64
FullName, Email string
}
// We do no require any special syntax to access field because receiver is a pointer
func (user *User) SendEmail(email string) {
fmt.Printf("Sent email to: %s\n", user.Email)
}
// ChangeMail will modify the users email because the receiver type is a ponter
func (user *User) ChangeEmail(email string) {
user.Email = email;
}
func main() {
user := User{
1,
"Zelalem Mekonen",
"[email protected]",
}
user.SendEmail("Hello") // Sent email to: [email protected]
user.ChangeEmail("[email protected]")
fmt.Println(user.Email) // [email protected]
}
Schnittstelle & Polymorphismus
Schnittstellen bieten eine Möglichkeit, das Verhalten eines Objekts anzugeben. Wenn dies möglich ist, kann es hier verwendet werden. Eine Schnittstelle definiert eine Reihe von Methoden. Diese Methoden enthalten jedoch keinen Code, da sie abstrakt sind oder die Implementierung dem Benutzer der Schnittstelle überlassen wird. Im Gegensatz zu den meisten objektorientierten Sprachen können Schnittstellen in Go Variablen enthalten.
Polymorphismus ist die Essenz der objektorientierten Programmierung: Die Fähigkeit, Objekte unterschiedlichen Typs einheitlich zu behandeln, solange sie an derselben Schnittstelle haften. Go-Schnittstellen bieten diese Funktion auf eine direkte und intuitive Weise
package main
type Runner interface {
Run()
}
type Admin struct {
Username, Password string
}
func (admin Admin) Run() {
fmt.Println("Admin ==> Run()");
}
type User struct {
ID uint64
FullName, Email string
}
func (user User) Run() {
fmt.Println("User ==> Run()")
}
// RunnerExample takes any type that fullfils the Runner interface
func RunnerExample(r Runner) {
r.Run()
}
func main() {
admin := Admin{
"zola",
"supersecretpassword",
}
user := User{
1,
"Zelalem Mekonen",
"[email protected]",
}
RunnerExample(admin)
RunnerExample(user)
}