Files
build-web-application-with-…/de/02.4.md
Sebastian c2e67b927b Fix Typo
2016-12-16 19:00:50 +01:00

215 lines
7.8 KiB
Markdown

# 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 ein `string` und wird genutzt, um den Namen einer Person zu speichern.
- `alter` is vom Typ `int` 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)
}
![](images/2.4.student_struct.png?raw=true)
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](preface.md)
- Vorheriger Abschnitt: [Kontrollstrukturen und Funktionen](02.3.md)
- Nächster Abschnitt: [Objektorientiertes Programmieren](02.5.md)