0Pricing
Go Academy · Lekcja

Wskaźniki i funkcje

Przekazywanie przez wartość a przekazywanie przez wskaźnik

Wskaźniki i funkcje to bezpłatna lekcja Go Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Go Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Go Academy zawiera 4 lekcji w sumie.

Przekazywanie przez wartość

Go przekazuje wszystkie argumenty funkcji przez wartość — tworzona jest kopia. Zmiany wewnątrz funkcji nie wpływają na oryginał:

package main
import "fmt"

func increment(n int) { n++ }

func main() {
    x := 5
    increment(x)
    fmt.Println(x) // 5 — unchanged
}

Przekazywanie przez wskaźnik

Przekaż wskaźnik, aby umożliwić funkcji modyfikowanie oryginalnej wartości:

package main
import "fmt"

func increment(n *int) { *n++ }

func main() {
    x := 5
    increment(&x)
    fmt.Println(x) // 6
}

Zwracanie wskaźników

Funkcje mogą zwracać wskaźniki do wartości alokowanych na stercie. Analiza ucieczki w Go zapewnia bezpieczeństwo:

package main
import "fmt"

func newInt(v int) *int { return &v }

func main() {
    p := newInt(42)
    fmt.Println(*p) // 42
}

Wydajne przekazywanie dużych struktur

Przekazywanie dużej struktury przez wskaźnik pozwala uniknąć kosztownego kopiowania:

package main
import "fmt"

type BigData struct{ Data [1024]int }

func process(d *BigData) { d.Data[0] = 99 }

func main() {
    bd := BigData{}
    process(&bd)
    fmt.Println(bd.Data[0]) // 99
}

Wskaźnik do interfejsu

Rzadko potrzebne — interfejsy już wewnętrznie przechowują wskaźnik. Przekazywanie *interface{} jest niemal zawsze błędem:

package main
import "fmt"

type Stringer interface{ String() string }

func print(s Stringer) { fmt.Println(s.String()) }

// Pass interface directly, NOT *Stringer
type Name string
func (n Name) String() string { return string(n) }

func main() {
    print(Name("Alice"))
}

Parametry opcjonalne za pomocą wskaźników

Użyj parametrów będących wskaźnikami, aby odróżnić „niepodano” od wartości zerowej:

package main
import "fmt"

func greet(name *string) {
    if name == nil {
        fmt.Println("Hello, stranger")
        return
    }
    fmt.Println("Hello,", *name)
}

func main() {
    s := "Alice"
    greet(&s)
    greet(nil)
}

Modyfikowanie za pośrednictwem wycinków

Wycinki już zawierają wewnętrzny wskaźnik, więc często nie potrzebujesz *[]T. Jednak gdy append ponownie alokuje pamięć, potrzebujesz wskaźnika do samego wycinka:

package main
import "fmt"

func addItem(s *[]int, v int) { *s = append(*s, v) }

func main() {
    nums := []int{1, 2, 3}
    addItem(&nums, 4)
    fmt.Println(nums) // [1 2 3 4]
}

Aliasing wskaźników

Wiele wskaźników wskazujących tę samą zmienną tworzy aliasing — zmiana dokonana za pośrednictwem jednego wskaźnika jest widoczna za pośrednictwem wszystkich pozostałych:

package main
import "fmt"

func main() {
    x := 10
    a, b := &x, &x
    *a = 99
    fmt.Println(*b) // 99 — same memory
}

Unikanie nadmiernego użycia wskaźników

Używaj wskaźników tylko wtedy, gdy jest to konieczne:

  • Modyfikowanie wartości wewnątrz funkcji
  • Duże struktury (>= ~64 bajtów)
  • nil jako oznaczenie braku wartości

Nadmierne używanie wskaźników zwiększa obciążenie modułu GC i zmniejsza czytelność kodu.

Wzorzec wskaźników do funkcji

Przechowuj wskaźniki do funkcji w mapie, aby utworzyć tabelę dyspozycji:

package main
import "fmt"

func add(a, b int) int { return a + b }
func sub(a, b int) int { return a - b }

func main() {
    ops := map[string]func(int,int)int{
        "+": add, "-": sub,
    }
    fmt.Println(ops["+"](10, 3)) // 13
    fmt.Println(ops["-"](10, 3)) // 7
}

Szybkie sprawdzenie

Jak umożliwić funkcji modyfikowanie zmiennej typu integer zdefiniowanej w kodzie wywołującym?

Podsumowanie

Najważniejsze informacje:

  • Go przekazuje argumenty przez wartość — używaj wskaźników do modyfikowania wartości
  • Zwracaj wskaźniki z konstruktorów, aby alokować wartości na stercie
  • Wycinki zawierają wewnętrzny wskaźnik, ale append może wymagać *[]T
  • Unikaj nadmiernego używania wskaźników — dla małych typów preferuj wartości

Polecenie ćwiczeniowe

Napisz funkcję normalize, która przyjmuje *[]string i konwertuje wszystkie ciągi znaków na małe litery bezpośrednio w miejscu, używając strings.ToLower.

Często zadawane pytania

Czy lekcja „Wskaźniki i funkcje” jest bezpłatna?

Tak — pełny tekst „Wskaźniki i funkcje” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Go Academy, przejdź na CoddyKit PRO. Kurs Go Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Wskaźniki i funkcje”?

Przekazywanie przez wartość a przekazywanie przez wskaźnik Ćwiczysz Go Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Go Academy?

Nie wymagamy żadnego doświadczenia. Go Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Wskaźniki i funkcje”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Go Academy?

Tak. Każda lekcja Go Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Czym są wskaźniki?
  2. Wskaźniki i funkcje
  3. Odbiorniki wskaźnikowe metod
  4. new() i kiedy używać wskaźników
← Powrót do Go Academy