2.4 Struct
Struct
Wie in anderen Programmiersprachen können wir auch in Go neue Datentypen erstellen, die als eine "Struktur" verknüpfte Eigenschaften oder Felder zusammenfasst. So können wir Beipielsweise einen neuen Datentyp person
erschaffen, dessen Eingenschaften der Name und das Alter einer Person sind. Wir nennen diesen Datentyp struct
.
type person struct {
name string
alter int
}
Es sieht ziemlich einfach aus, ein struct
zu definieren, nicht?
Es gibt insgesamt zwei Eigenschaften.
name
ist einstring
und wird genutzt, um den Namen einer Person zu speichern.alter
is vom Typint
und beinhaltet das Alter einer Person.
Schauen wir uns das einmal praktisch an.
type person struct {
name string
alter int
}
var P person // p ist vom Typ person
P.name = "Astaxie" // Weise "Astaxie" der Eigenschaft 'name' von p zu
P.alter = 25 // Weise 25 der Eigenschaft 'alter' von p zu
fmt.Printf("Der Name der Person lautet %s\n", P.name) // Rufe die Eigenschaft 'name' von p auf
Es gibt noch drei weitere Wege, ein Struct zu definieren.
Weise Startwerte in der Reihenfolge der Eigenschaften zu.
P := person{"Tom", 25}
Oder nutze das Schema
Eigenschaft:Wert
, um ein Struct zu erstellen, ohne dabei auf die Reihenfolge achten zu müssen.P := person{alter:24, name:"Bob"}
Definiere ein "anonymes" Struct und vergebe Startwerte
P := struct{name string; alter int}{"Amy",18}
Schauen wir uns das vollständige Beispiel an.
package main
import "fmt"
// Definiere einen neuen Datentyp
type person struct {
name string
alter int
}
// Vergleiche das Alter von zwei Personen. Dann gibt die ältere Person und den Altersunterschied zurück
// Structs werden als normaler Wert übergeben
func Älter(p1, p2 person) (person, int) {
if p1.alter>p2.alter {
return p1, p1.alter-p2.alter
}
return p2, p2.alter-p1.alter
}
func main() {
var tom person
// Initialisierung
tom.name, tom.alter = "Tom", 18
// Initialisiere zwei Werte nach dem Schema "Eigenschaft:Wert"
bob := person{alter:25, name:"Bob"}
// Initialisiere die Eigenschaft nach der Reihenfolge
paul := person{"Paul", 43}
tb_Älter, tb_diff := Älter(tom, bob)
tp_Älter, tp_diff := Älter(tom, paul)
bp_Älter, bp_diff := Älter(bob, paul)
fmt.Printf("Von %s und %s ist %s um %d Jahre älter\n", tom.name, bob.name, tb_Älter.name, tb_diff)
fmt.Printf("Von %s und %s ist %s um %d Jahre älter\n", tom.name, paul.name, tp_Älter.name, tp_diff)
fmt.Printf("Von %s und %s ist %s um %d Jahre älter\n", bob.name, paul.name, bp_Älter.name, bp_diff)
}
Eigenschaften in Structs einbetten
Soeben habe ich Dir gezeigt, wie Du ein Struct mit Eigenschaften und Datentypen definieren kannst. Aber Go unterstützt auch Eigenschaften, die keinen Namen besitzen und nur dessen Datentyp angegeben wird. Wir bezeichnen diese als eingebettete Eigenschaften.
Wenn die eingebette Eigenschaft ein weiteres Struct ist, dann all seine Eigenschaften in den Struct übertragen, in dem es eingebettet wurde.
Betrachten wir ein Beispiel.
package main
import "fmt"
type Mensch struct {
name string
alter int
gewicht int
}
type Student struct {
Mensch // Eingebettete Eigenschaft, d.h. Student besitzt alle Eigenschaften von Mensch.
fachgebiet string
}
func main() {
// Initialisierng eines Studenten
mark := Student{Mensch{"Mark", 25, 120}, "Informatik"}
// Eigenschaften aufrufen
fmt.Println("Sein Name lautet ", mark.name)
fmt.Println("Sein Alter ist ", mark.alter)
fmt.Println("Er wiegt ", mark.gewicht)
fmt.Println("Sein Fachgebiet ist ", mark.fachgebiet)
// Eigenschaften verändern
mark.fachgebiet = "Künstliche Intelligenz"
fmt.Println("Mark hat sein Fachgebiet gewechselt")
fmt.Println("Sein Fachgebiet lautet ", mark.fachgebiet)
// Alter ändern
fmt.Println("Mark wurde alt")
mark.alter = 46
fmt.Println("Sein Alter beträgt ", mark.alter, " Jahre")
// Gewicht ändern
fmt.Println("Mark ist kein Athlet mehr")
mark.gewicht += 60
fmt.Println("Er wiegt nun", mark.gewicht)
}
Abbildung 2.7 Einbettung von Mensch in Student
Wie Du siehst, können wir die Eigenschaften alter
und name
vom Typ Student genauso aufrufen, wie jene vom Typ Mensch. Genau so funktioniert das Einbetten. Ziemlich einfach, nicht wahr? Aber es gibt noch Kleinigkeit, die ich Dir zeigen möchte. Du kannst auch den Typ Mensch verwenden, um auf Eigenschaften von Student zurückzugreifen.
mark.Mensch = Mensch{"Marcus", 55, 220}
mark.Mensch.alter -= 1
In Go können alle Datenttypen eingebettet werden.
package main
import "fmt"
type Fähigkeiten []string
type Mensch struct {
name string
alter int
gewicht int
}
type Student struct {
Mensch // Struct als eingebettete Eigenschaft
Fähigkeiten // Slice vom Typ string als eingebettete Eigenschaft
int // Standard Datentyp als eingebettete Eigenschaft
fachgebiet string
}
func main() {
// Initialisiere Studentin Jane
jane := Student{Mensch:Mensch{"Jane", 35, 100}, fachgebiet:"Biologie"}
// Eigenschaften aufrufen
fmt.Println("Ihr Name lautet ", jane.name)
fmt.Println("Ihr Alter ist ", jane.alter)
fmt.Println("Sie wiegt ", jane.gewicht)
fmt.Println("Ihr Fachgebiet ist ", jane.fachgebiet)
// Änderung des Wertes der Eigenschaft fähigkeit
jane.Fähigkeiten = []string{"Anatomie"}
fmt.Println("Sie besitzt folgende Fähigkeiten: ", jane.Fähigkeiten)
fmt.Println("Sie hat zwei neue Fähigkeiten erworben ")
jane.Fähigkeiten = append(jane.Fähigkeiten, "Physik", "Golang")
fmt.Println("Sie besitzt nun folgende Fähigkeiten ", jane.Fähigkeiten)
// Veränderung einer eingebetteten Eigenschaft
jane.int = 3
fmt.Println("Ihre bevorzugte Nummer lautet", jane.int)
}
Im oberen Beispiel ist erkenntlich, dass alle Datentypen eingebettet werden und Funktionen auf ihre Werte zugreifen können.
Aber es gibt noch ein kleines Problem. Was geschieht, wenn Mensch die Eigenschaft telefon
besitzt und Student eine Eigenschaft mit dem gleichen Namen besitzt?
Go nutzt einen einfachen Weg zur Unterscheidung. Um die Eigenschaft telefon
von Student zu erhalten, nutzt Du weiterhein Student.telefon
. Die gleichnahmige Eigenschaft von Mensch kannst Du erhalten, indem Du Student.Mensch.telefon
verwendest. Wie Du siehst, muss einfach der eingebette Datentyp vorangestellt werden. Diese Fähigkeiten wird "überladen" genannt (im Englischen overloading
).
package main
import "fmt"
type Mensch struct {
name string
alter int
telefon string // Mensch hat die Eigenschaft telefon
}
type Mitarbeiter struct {
Mensch // Eingebetter Datentyp Mensch
spezialisierung string
telefon string // Eigenschaft telefon in Mitarbeiter
}
func main() {
Bob := Mitarbeiter{Mensch{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
fmt.Println("Bobs berufliche Telefonnummer lautet ", Bob.telefon)
// Greife auf Eigenschaft telefon in Mensch zu
fmt.Println("Bobs private Telefonnummer lauet ", Bob.Mensch.telefon)
}
Links
- Inhaltsverzeichnis
- Vorheriger Abschnitt: Kontrollstrukturen und Funktionen
- Nächster Abschnitt: Objektorientiertes Programmieren