Menu
Coddy logo textTech

Grundlagen des Struct Embedding

Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 35 von 107.

Struct-Embedding ist Gos Mechanismus, um einen struct-Typ in einen anderen einzuschließen. Anstatt einen Feldnamen zu verwenden, geben Sie einfach den Typ an, und Go reicht die Felder des eingebetteten structs an das äußere struct weiter.

Hier ist die grundlegende Syntax:

type Address struct {
    City    string
    Country string
}

type Person struct {
    Name string
    Address  // eingebettet - kein Feldname
}

Wenn Sie Address in Person einbetten, können Sie direkt über das äußere Struct auf die eingebetteten Felder zugreifen:

func main() {
    p := Person{
        Name: "Alice",
        Address: Address{
            City:    "London",
            Country: "UK",
        },
    }
    
    fmt.Println(p.City)     // London - direkter Zugriff
    fmt.Println(p.Country)  // UK - direkter Zugriff
    fmt.Println(p.Address.City)  // funktioniert ebenfalls
}

Beachten Sie, wie p.City funktioniert, ohne explizit p.Address.City zu schreiben. Go macht die Felder des eingebetteten Structs automatisch verfügbar, sodass sie so zugänglich sind, als gehörten sie zum äußeren Struct. Sie können bei Bedarf weiterhin über den Namen des eingebetteten Typs auf sie zugreifen.

Dies unterscheidet sich von regulären verschachtelten Structs, bei denen Sie immer den Feldnamen verwenden müssen, um auf innere Felder zuzugreifen. Embedding erzeugt eine flachere, bequemere API, während die logische Gruppierung verwandter Daten beibehalten wird.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Fahrzeugregistrierungssystem bauen, das Struct-Embedding verwendet, um ein sauberes, organisiertes Datenmodell zu erstellen. Sie werden die Kontaktinformationen von den Fahrzeugdetails trennen und gleichzeitig den direkten Zugriff auf alle Felder durch Einbettung ermöglichen.

Sie werden Ihren Code auf zwei Dateien aufteilen:

  • vehicle.go: Erstellen Sie zwei Structs, die durch Einbettung zusammenarbeiten:
    • Ein ContactInfo-Struct mit den Feldern OwnerName und Phone (beides Strings)
    • Ein Vehicle-Struct, das ContactInfo einbettet (ohne Feldnamen) und seine eigenen Felder Make, Model und Year hinzufügt
    Erstellen Sie außerdem eine Methode namens Summary für Vehicle, die einen formatierten String mit allen Fahrzeug- und Kontaktinformationen zurückgibt.
  • main.go: Lesen Sie Fahrzeug- und Besitzerdetails aus der Eingabe ein, erstellen Sie eine Vehicle-Instanz mit eingebettetem ContactInfo und demonstrieren Sie den Zugriff auf die eingebetteten Felder sowohl direkt als auch über den Namen des eingebetteten Typs. Geben Sie am Ende die Fahrzeugzusammenfassung aus.

Die folgenden Eingaben werden bereitgestellt:

  • Zeile 1: Name des Besitzers
  • Zeile 2: Telefonnummer
  • Zeile 3: Fahrzeugmarke
  • Zeile 4: Fahrzeugmodell
  • Zeile 5: Jahr (Ganzzahl)

Ihre Summary-Methode sollte einen String in diesem Format zurückgeben:

[Year] [Make] [Model] - Owner: [OwnerName], Phone: [Phone]

Demonstrieren Sie in Ihrer Hauptdatei die Feld-Promotion (Field Promotion), indem Sie Folgendes ausgeben:

  1. Den Namen des Besitzers, direkt über das Vehicle aufgerufen (z. B. v.OwnerName)
  2. Die Telefonnummer, aufgerufen über den eingebetteten Typ (z. B. v.ContactInfo.Phone)
  3. Die vollständige Zusammenfassung aus Ihrer Summary-Methode

Zum Beispiel, gegeben Alice Smith, 555-1234, Toyota, Camry und 2023, sollte Ihre Ausgabe wie folgt aussehen:

Alice Smith
555-1234
2023 Toyota Camry - Owner: Alice Smith, Phone: 555-1234

Beachten Sie, wie beide Zugriffsmuster funktionieren – der direkte Zugriff durch Feld-Promotion und der explizite Zugriff über den Namen des eingebetteten Typs – was Ihnen Flexibilität bei der Arbeit mit eingebetteten Daten gibt.

Spickzettel

Das Einbetten von Structs (Struct embedding) ermöglicht es Ihnen, einen Struct-Typ in einen anderen einzubinden, ohne einen Feldnamen anzugeben. Die Felder des eingebetteten Structs werden in den äußeren Struct "promoted" (hochgestuft), wodurch sie direkt zugänglich sind.

Basissyntax

type Address struct {
    City    string
    Country string
}

type Person struct {
    Name string
    Address  // embedded - no field name
}

Zugriff auf eingebettete Felder

Sie können auf zwei Arten auf eingebettete Felder zugreifen:

p := Person{
    Name: "Alice",
    Address: Address{
        City:    "London",
        Country: "UK",
    },
}

// Direct access (field promotion)
fmt.Println(p.City)     // London

// Through embedded type name
fmt.Println(p.Address.City)  // London

Go stuft die Felder des eingebetteten Structs automatisch hoch, was den direkten Zugriff ermöglicht, als ob sie zum äußeren Struct gehören würden. Bei Bedarf können Sie weiterhin über den Namen des eingebetteten Typs auf sie zugreifen.

Probier es selbst

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Besitzernamen lesen
	ownerName, _ := reader.ReadString('\n')
	ownerName = strings.TrimSpace(ownerName)

	// Telefonnummer lesen
	phone, _ := reader.ReadString('\n')
	phone = strings.TrimSpace(phone)

	// Fahrzeugmarke lesen
	make, _ := reader.ReadString('\n')
	make = strings.TrimSpace(make)

	// Fahrzeugmodell lesen
	model, _ := reader.ReadString('\n')
	model = strings.TrimSpace(model)

	// Jahr lesen
	yearStr, _ := reader.ReadString('\n')
	yearStr = strings.TrimSpace(yearStr)
	year, _ := strconv.Atoi(yearStr)

	// TODO: Erstelle eine Vehicle-Instanz mit eingebettetem ContactInfo
	// Verwende die oben aus der Eingabe gelesenen Werte

	// TODO: Gib den Besitzernamen aus, auf den direkt über das Vehicle zugegriffen wird (field promotion)
	// Beispiel: fmt.Println(v.OwnerName)

	// TODO: Gib die Telefonnummer aus, auf die über den Namen des eingebetteten Typs zugegriffen wird
	// Beispiel: fmt.Println(v.ContactInfo.Phone)

	// TODO: Gib die vollständige Zusammenfassung mit der Summary-Methode aus
	// Beispiel: fmt.Println(v.Summary())

	// Entferne diese Zeilen, sobald du die Lösung implementiert hast
	_ = ownerName
	_ = phone
	_ = make
	_ = model
	_ = year
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung