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)
niljako 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
appendmoż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.