Menu
Coddy logo textTech

Przekazywanie przez wartość a przez referencję

Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 21 z 107.

Go jest językiem przekazywania przez wartość. Gdy przekazujesz zmienną do funkcji, Go tworzy kopię tej wartości. Oznacza to, że zmiany wprowadzone wewnątrz funkcji nie wpływają na oryginalną zmienną.

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

func main() {
    x := 10
    double(x)
    fmt.Println(x)  // 10 (bez zmian)
}

To samo dotyczy struktur. Przekazanie struktury do funkcji kopiuje wszystkie jej pola, więc zmiany wprowadzone wewnątrz funkcji zostają utracone.

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 (bez zmian)
}

Aby zmodyfikować oryginalną wartość, przekaż zamiast tego . Sam wskaźnik jest kopiowany, ale nadal wskazuje ten sam adres pamięci, co pozwala zmienić oryginalne dane.

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

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

Używaj wskaźników, gdy chcesz zmodyfikować oryginalną wartość lub przekazać duże struktury, aby uniknąć kosztownego kopiowania. Używaj wartości, gdy chcesz chronić oryginalne dane przed niezamierzonymi zmianami.

challenge icon

Wyzwanie

Łatwy

Stwórzmy system koszyka zakupowego, który pokazuje różnicę między przekazywaniem struktur przez wartość a przekazywaniem ich przez wskaźnik. Zobaczysz na własne oczy, że tylko parametry będące wskaźnikami mogą modyfikować oryginalne dane.

Rozmieścisz swój kod w dwóch plikach:

  • cart.go: Zdefiniuj strukturę CartItem z polami Name (string), Price (float64) i Quantity (int). Utwórz dwie funkcje, które spróbują zaktualizować ilość:
    • UpdateQuantityByValue przyjmuje CartItem (przez wartość) i nową ilość, a następnie ustawia ilość elementu na nową wartość
    • UpdateQuantityByPointer przyjmuje *CartItem (wskaźnik) i nową ilość, a następnie ustawia ilość elementu na nową wartość
    Utwórz również metodę Total dla CartItem, która zwraca cenę pomnożoną przez ilość.
  • main.go: Odczytaj szczegóły elementu z danych wejściowych, utwórz CartItem, a następnie zademonstruj oba sposoby aktualizacji. Najpierw spróbuj zaktualizować ilość za pomocą funkcji przyjmującej wartość i pokaż wynik, a następnie ponownie zaktualizuj ją za pomocą funkcji przyjmującej wskaźnik i pokaż wynik.

Podane zostaną następujące dane wejściowe:

  • Wiersz 1: Nazwa elementu
  • Wiersz 2: Cena (liczba zmiennoprzecinkowa)
  • Wiersz 3: Początkowa ilość (liczba całkowita)
  • Wiersz 4: Nowa ilość do ustawienia (liczba całkowita)

Format wyjściowy:

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

Na przykład dla danych wejściowych Laptop, 999.99, 1 i 3 wynik powinien wyglądać tak:

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

Zwróć uwagę, że ilość pozostaje równa 1 po aktualizacji przez wartość (funkcja zmodyfikowała kopię), ale zmienia się na 3 po aktualizacji przez wskaźnik (funkcja zmodyfikowała oryginał). Formatuj sumy z dokładnością do dwóch miejsc po przecinku.

Spróbuj swoich sił

package main

import (
	"fmt"
)

func main() {
	// Wczytaj dane wejściowe
	var name string
	var price float64
	var initialQty, newQty int

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

	// TODO: Utwórz CartItem z wartościami wejściowymi

	// TODO: Wypisz stan początkowy, używając formatu:
	// fmt.Printf("Initial: %s x%d = $%.2f\n", ...)

	// TODO: Spróbuj zaktualizować ilość za pomocą UpdateQuantityByValue
	// Następnie wypisz wynik (zauważ, że ilość się nie zmieni)

	// TODO: Zaktualizuj ilość za pomocą UpdateQuantityByPointer
	// Następnie wypisz wynik (zauważ, że ilość się zmieni)
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Go online