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)
}

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)
}

results matching ""

    No results matching ""