Uruchamianie goroutines
Słowo kluczowe go, cykl życia goroutines i WaitGroups
Uruchamianie goroutines to bezpłatna lekcja Go Academy na CoddyKit. To lekcja 1 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.
Czym jest gorutyna?
Gorutyna to lekka funkcja wykonywana współbieżnie i zarządzana przez środowisko uruchomieniowe Go. Gorutyny są znacznie tańsze niż wątki systemu operacyjnego — można uruchamiać ich tysiące:
- Uruchamianie za pomocą słowa kluczowego
go - Początkowy stos ma około 2 KB i rośnie dynamicznie
- Planowaniem zajmuje się środowisko uruchomieniowe Go, a nie system operacyjny
- Komunikacja odbywa się przez kanały, a nie przez pamięć współdzieloną
Słowo kluczowe go
Dowolne wywołanie funkcji można poprzedzić słowem kluczowym go, aby uruchomić je jako gorutynę:
package main
import ("fmt"; "time")
func greet(name string) {
fmt.Printf("Hello, %s!\n", name)
}
func main() {
go greet("Alice") // runs concurrently
go greet("Bob") // runs concurrently
time.Sleep(100 * time.Millisecond) // wait for goroutines
fmt.Println("done")
}Cykl życia gorutyny
Gorutyna rozpoczyna działanie w chwili wykonania instrukcji go i kończy je, gdy jej funkcja zwróci wynik. Jeśli funkcja main zakończy działanie, wszystkie gorutyny zostają zakończone:
package main
import ("fmt"; "time")
func worker(id int) {
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Duration(id) * 50 * time.Millisecond)
fmt.Printf("Worker %d done\n", id)
}
func main() {
for i := 1; i <= 3; i++ {
go worker(i)
}
time.Sleep(300 * time.Millisecond) // naive wait
}sync.WaitGroup do koordynacji
Zamiast funkcji sleep należy używać sync.WaitGroup do oczekiwania na zakończenie gorutyn:
package main
import ("fmt"; "sync")
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // signal completion
fmt.Printf("Worker %d working\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1) // register one goroutine
go worker(i, &wg)
}
wg.Wait() // block until all Done()
fmt.Println("all workers finished")
}Anonimowe gorutyny
Anonimową funkcję można uruchomić bezpośrednio jako gorutynę — jest to przydatne w przypadku wbudowanych zadań współbieżnych:
package main
import ("fmt"; "sync")
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
i := i // capture loop variable
wg.Add(1)
go func() {
defer wg.Done()
fmt.Printf("goroutine %d\n", i)
}()
}
wg.Wait()
}Pułapka przechwytywania zmiennej pętli
Bez przechwycenia zmiennej pętli wszystkie gorutyny mogą zobaczyć tę samą wartość (końcową) — jest to klasyczny błąd współbieżności w Go:
package main
import ("fmt"; "sync")
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func(n int) { // pass i as argument — safe
defer wg.Done()
fmt.Println(n) // prints 0, 1, 2 in some order
}(i)
}
wg.Wait()
}Gorutyny a wątki
Dlaczego gorutyny są preferowane zamiast wątków systemu operacyjnego:
- Początkowy stos ma 2 KB, a wątki systemu operacyjnego około 1 MB
- Ich utworzenie trwa mikrosekundy zamiast milisekund
- Środowisko uruchomieniowe Go przeplata gorutyny na wątkach systemu operacyjnego określonych przez GOMAXPROCS
- Przełączanie gorutyn odbywa się kooperacyjnie — bez udziału jądra
- Go zajmuje się planowaniem, więc można skupić się na logice programu
GOMAXPROCS
runtime.GOMAXPROCS określa, ile wątków systemu operacyjnego może równolegle wykonywać gorutyny (domyślnie jest to liczba procesorów):
package main
import ("fmt"; "runtime")
func main() {
// Default: number of available CPU cores
fmt.Println("CPUs:", runtime.NumCPU())
fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0)) // 0 = query without changing
// Set to 1 for debugging race conditions:
// runtime.GOMAXPROCS(1)
fmt.Println("Goroutines:", runtime.NumGoroutine())
}Wycieki gorutyn
Do wycieku gorutyny dochodzi, gdy gorutyna zostaje uruchomiona, ale nigdy się nie kończy. Typowe przyczyny to zablokowany odbiór z kanału, zablokowany mutex lub brak anulowania:
package main
import ("fmt"; "time"; "runtime")
func leaky() {
ch := make(chan int) // nobody sends to ch
go func() {
v := <-ch // blocks forever — goroutine leaked!
fmt.Println(v)
}()
}
func main() {
leaky()
time.Sleep(10 * time.Millisecond)
fmt.Println("goroutines:", runtime.NumGoroutine()) // > 1
}Dobre praktyki dotyczące gorutyn
Wskazówki dotyczące gorutyn:
- Zawsze należy wiedzieć, w jaki sposób gorutyna się zakończy
- Do synchronizacji należy używać WaitGroup lub kanałów, a nie funkcji sleep
- Zmienne pętli należy przekazywać jako argumenty funkcji, a nie za pomocą domknięcia
- Gorutyny należy anulować za pomocą context, zamiast pozostawiać je uruchomione
- Należy używać detektora wyścigów danych:
go run -race main.go
Szybki test
Jaki jest prawidłowy sposób uniknięcia błędu przechwytywania zmiennej pętli w gorutynach?
Podsumowanie: uruchamianie gorutyn
Podsumowanie:
- Uruchamianie za pomocą
go fn()— lekkie i tanie - Do oczekiwania należy używać
sync.WaitGroup:Add(1),defer Done(),Wait() - Zmienne pętli należy przechwytywać jako argument lub przez ponowną deklarację
- Zawsze należy wiedzieć, jak każda gorutyna się kończy — zapobiega to wyciekom
- Flagi
-racenależy używać do wykrywania wyścigów danych
Często zadawane pytania
Czy lekcja „Uruchamianie goroutines” jest bezpłatna?
Tak — pełny tekst „Uruchamianie goroutines” 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 „Uruchamianie goroutines”?
Słowo kluczowe go, cykl życia goroutines i WaitGroups Ć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 1 z 4.
Ile czasu zajmuje lekcja „Uruchamianie goroutines”?
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
- Uruchamianie goroutines
- Kanały niebuforowane
- Kanały buforowane
- Kierunek kanałów i wzorce potoków