Menu
Coddy logo textTech

Übergabe per Wert vs. Referenz

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

Go ist eine Pass-by-Value-Sprache. Wenn Sie eine Variable an eine Funktion übergeben, erstellt Go eine Kopie dieses Wertes. Das bedeutet, dass Änderungen innerhalb der Funktion die ursprüngliche Variable nicht beeinflussen.

func double(n int) {
    n = n * 2
}

func main() {
    x := 10
    double(x)
    fmt.Println(x)  // 10 (unverändert)
}

Das Gleiche gilt für Structs. Das Übergeben eines Structs an eine Funktion kopiert alle seine Felder, sodass Änderungen innerhalb der Funktion verloren gehen.

type Person struct {
    Name string
    Age  int
}

func birthday(p Person) {
    p.Age++
}

func main() {
    alice := Person{Name: "Alice", Age: 30}
    birthday(alice)
    fmt.Println(alice.Age)  // 30 (unverändert)
}

Um den ursprünglichen Wert zu ändern, übergeben Sie stattdessen einen Pointer. Der Pointer selbst wird kopiert, aber er zeigt immer noch auf dieselbe Speicheradresse, was es Ihnen ermöglicht, die ursprünglichen Daten zu ändern.

func birthday(p *Person) {
    p.Age++
}

func main() {
    alice := Person{Name: "Alice", Age: 30}
    birthday(&alice)
    fmt.Println(alice.Age)  // 31 (geändert!)
}

Verwenden Sie Pointer, wenn Sie den ursprünglichen Wert ändern müssen oder wenn Sie große Structs übergeben, um teures Kopieren zu vermeiden. Verwenden Sie Werte, wenn Sie die ursprünglichen Daten vor unbeabsichtigten Änderungen schützen möchten.

challenge icon

Aufgabe

Einfach

Erstelle ein Warenkorbsystem, das den Unterschied zwischen der Übergabe von Strukturen als Wert und als Zeiger veranschaulicht. Du wirst unmittelbar sehen, dass nur Zeigerparameter die ursprünglichen Daten ändern können.

Du organisierst deinen Code über zwei Dateien:

  • cart.go: Definiere eine CartItem-Struktur mit den Feldern Name (string), Price (float64) und Quantity (int). Erstelle zwei Funktionen, die versuchen, die Menge zu aktualisieren:
    • UpdateQuantityByValue nimmt ein CartItem (als Wert) und eine neue Menge entgegen und setzt anschließend die Menge des Artikels auf den neuen Wert
    • UpdateQuantityByPointer nimmt ein *CartItem (einen Zeiger) und eine neue Menge entgegen und setzt anschließend die Menge des Artikels auf den neuen Wert
    Erstelle außerdem eine Total-Methode für CartItem, die den mit der Menge multiplizierten Preis zurückgibt.
  • main.go: Lies die Artikeldaten aus der Eingabe ein, erstelle ein CartItem und führe anschließend beide Aktualisierungsansätze vor. Versuche zuerst, die Aktualisierung mit der Wertfunktion durchzuführen, und gib das Ergebnis aus. Aktualisiere danach mit der Zeigerfunktion und gib das Ergebnis erneut aus.

Die folgenden Eingaben werden bereitgestellt:

  • Zeile 1: Artikelname
  • Zeile 2: Preis (Gleitkommazahl)
  • Zeile 3: Anfangsmenge (Ganzzahl)
  • Zeile 4: Zu setzende neue Menge (Ganzzahl)

Ausgabeformat:

Initial: [Name] x[Quantity] = $[Total]
After value update: [Name] x[Quantity] = $[Total]
After pointer update: [Name] x[Quantity] = $[Total]

Bei den Eingaben Laptop, 999.99, 1 und 3 sollte deine Ausgabe beispielsweise folgendermaßen aussehen:

Initial: Laptop x1 = $999.99
After value update: Laptop x1 = $999.99
After pointer update: Laptop x3 = $2999.97

Beachte, dass die Menge nach der Aktualisierung per Wert bei 1 bleibt (die Funktion hat eine Kopie geändert), sich nach der Aktualisierung per Zeiger jedoch auf 3 ändert (die Funktion hat das Original geändert). Formatiere die Gesamtsummen mit zwei Dezimalstellen.

Probier es selbst

package main

import (
	"fmt"
)

func main() {
	// Eingabe lesen
	var name string
	var price float64
	var initialQty, newQty int

	fmt.Scanln(&name)
	fmt.Scanln(&price)
	fmt.Scanln(&initialQty)
	fmt.Scanln(&newQty)

	// TODO: Erstelle ein CartItem mit den Eingabewerten

	// TODO: Gib den Anfangszustand mit folgendem Format aus:
	// fmt.Printf("Initial: %s x%d = $%.2f\n", ...)

	// TODO: Versuche, die Menge mit UpdateQuantityByValue zu aktualisieren
	// Gib dann das Ergebnis aus (beachte, dass sich die Menge nicht ändern wird)

	// TODO: Aktualisiere die Menge mit UpdateQuantityByPointer
	// Gib dann das Ergebnis aus (beachte, dass sich die Menge ändern wird)
}
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

Übe selbstständig: Online-Go-Compiler