Menu
Coddy logo textTech

Zeiger auf Structs

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

Beim Arbeiten mit Structs werden Sie oft Pointer verwenden, um das Kopieren großer Datenstrukturen zu vermeiden und um das ursprüngliche Struct zu verändern. Ein Pointer auf ein Struct hält die Speicheradresse dieser Struct-Instanz.

Sie können einen Struct-Pointer erstellen, indem Sie den &-Operator auf ein bestehendes Struct anwenden oder den Adressoperator direkt mit einem Struct-Literal verwenden.

type Person struct {
    Name string
    Age  int
}

p := Person{Name: "Alice", Age: 30}
ptr := &p  // Zeiger auf ein bestehendes Struct

// Oder direkt erstellen
ptr2 := &Person{Name: "Bob", Age: 25}

Go bietet eine praktische Abkürzung beim Zugriff auf Struct-Felder über einen Pointer. Anstatt (*ptr).Name zu schreiben, können Sie einfach ptr.Name schreiben. Go dereferenziert den Pointer automatisch für Sie.

ptr := &Person{Name: "Alice", Age: 30}

// Beide funktionieren identisch
fmt.Println((*ptr).Name)  // explizite Dereferenzierung
fmt.Println(ptr.Name)     // automatische Dereferenzierung

Diese automatische Dereferenzierung gilt auch beim Ändern von Feldern. Änderungen über den Pointer wirken sich auf das ursprüngliche Struct aus.

p := Person{Name: "Alice", Age: 30}
ptr := &p

ptr.Age = 31           // verändert das Original
fmt.Println(p.Age)     // 31

Struct-Pointer sind in den OOP-Mustern von Go essenziell. Sie ermöglichen es Methoden, den Zustand des Receivers zu ändern, erlauben die effiziente Übergabe großer Structs an Funktionen und bilden die Grundlage für den Aufbau verknüpfter Datenstrukturen wie Bäume und Listen.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Bankkontosystem bauen, das demonstriert, wie Struct-Pointer es Ihnen ermöglichen, die ursprünglichen Daten effizient zu modifizieren. Sie werden ein Konto erstellen, das durch Pointer-Operationen aktualisiert werden kann.

Sie werden Ihren Code in zwei Dateien organisieren:

  • account.go: Definieren Sie ein BankAccount-Struct mit den Feldern Owner (string), Balance (float64) und AccountNumber (string). Erstellen Sie eine Funktion namens NewAccount, die einen Besitzernamen und eine Kontonummer als Parameter entgegennimmt und einen Pointer auf ein neues BankAccount mit einem Startguthaben von 0 zurückgibt. Erstellen Sie außerdem eine Deposit-Funktion, die einen *BankAccount-Pointer und einen Betrag entgegennimmt und diesen Betrag dann über den Pointer zum Guthaben des Kontos addiert.
  • main.go: Lesen Sie die Kontoinformationen aus der Eingabe ein, erstellen Sie ein Konto mit Ihrer Konstruktorfunktion (die einen Pointer zurückgibt), tätigen Sie eine Einzahlung unter Verwendung des Pointers und zeigen Sie die Kontodetails an, um zu bestätigen, dass das Guthaben geändert wurde.

Die folgenden Eingaben werden bereitgestellt:

  • Zeile 1: Besitzername
  • Zeile 2: Kontonummer
  • Zeile 3: Einzahlungsbetrag (float)

Ausgabeformat:

Account: [AccountNumber]
Owner: [Owner]
Balance: [Balance]

Zum Beispiel, gegeben John Smith, ACC-12345 und 500.50, sollte Ihre Ausgabe wie folgt aussehen:

Account: ACC-12345
Owner: John Smith
Balance: 500.50

Denken Sie daran, dass Ihre NewAccount-Funktion *BankAccount unter Verwendung des &-Operators zurückgeben sollte und Ihre Deposit-Funktion das Guthaben direkt über den Pointer modifizieren kann, indem sie Go's automatische Dereferenzierung nutzt (z. B. account.Balance anstelle von (*account).Balance).

Spickzettel

Ein Pointer auf ein Struct hält die Speicheradresse einer Struct-Instanz. Erstellen Sie Struct-Pointer mit dem &-Operator:

type Person struct {
    Name string
    Age  int
}

p := Person{Name: "Alice", Age: 30}
ptr := &p  // Pointer auf ein existierendes Struct

// Oder direkt erstellen
ptr2 := &Person{Name: "Bob", Age: 25}

Go bietet eine automatische Dereferenzierung beim Zugriff auf Struct-Felder über einen Pointer. Anstatt (*ptr).Name können Sie ptr.Name schreiben:

ptr := &Person{Name: "Alice", Age: 30}

// Beides funktioniert identisch
fmt.Println((*ptr).Name)  // explizite Dereferenzierung
fmt.Println(ptr.Name)     // automatische Dereferenzierung

Änderungen über einen Pointer wirken sich auf das ursprüngliche Struct aus:

p := Person{Name: "Alice", Age: 30}
ptr := &p

ptr.Age = 31           // modifiziert das Original
fmt.Println(p.Age)     // 31

Struct-Pointer ermöglichen es Methoden, den Zustand des Receivers zu ändern, erlauben die effiziente Übergabe großer Structs an Funktionen und bilden die Grundlage für verkettete Datenstrukturen.

Probier es selbst

package main

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

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// Name des Inhabers lesen
	ownerName, _ := reader.ReadString('\n')
	ownerName = strings.TrimSpace(ownerName)
	
	// Kontonummer lesen
	accountNumber, _ := reader.ReadString('\n')
	accountNumber = strings.TrimSpace(accountNumber)
	
	// Einzahlungsbetrag lesen
	amountStr, _ := reader.ReadString('\n')
	amountStr = strings.TrimSpace(amountStr)
	amount, _ := strconv.ParseFloat(amountStr, 64)
	
	// TODO: Erstelle ein neues Konto mit der Funktion NewAccount (gibt einen Pointer zurück)
	
	// TODO: Führe eine Einzahlung mit der Funktion Deposit und dem Konto-Pointer durch
	
	// TODO: Gib die Kontodetails im erforderlichen Format aus:
	// Account: [AccountNumber]
	// Owner: [Owner]
	// Balance: [Balance]
}
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