Goroutine — Go’ning eng mashhur xususiyati: funksiyani boshqa barcha kod bilan bir vaqtda, mustaqil ishga tushirish usuli. Goroutine oddiy OS thread’dan ancha “yengil” — bitta dasturda minglab, hatto millionlab goroutine osongina ishlaydi.
goroutine —
go funksiyaChaqiruvi()yozuvi orqali boshlanadigan, mustaqil ishlaydigan yengil ijro oqimi. Goroutine’lar bitta yoki bir nechta OS thread ustida, Go runtime tomonidan boshqariladi.
go kalit so’zi — goroutine boshlash
Har qanday funksiya chaqiruvi oldiga go qo’yish uni alohida goroutine’da ishga tushiradi:
package main
import "fmt"
func main() {
go fmt.Println("goroutine ichida")
fmt.Println("main tugadi")
}
main tugadi
E’tibor bering: "goroutine ichida" umuman chop etilmadi! Sababi — main funksiya goroutine tugashini kutmasdan davom etdi va dastur tezda tugadi, goroutine esa ishga ulgurmay qoldi. Bu Go’dagi eng muhim, boshida hayratlanarli haqiqat: main funksiyasi hech qanday goroutine’ni kutmaydi, agar unga aniq aytilmasa.
sync.WaitGroup — goroutine’larni kutish
Barcha goroutine tugashini kafolatlash uchun sync.WaitGroup ishlatiladi — u tugallanmagan ishlar sonini hisoblab boradi:
package main
import (
"fmt"
"sync"
)
func ishla(id int, natijalar []string, wg *sync.WaitGroup) {
defer wg.Done()
natijalar[id] = fmt.Sprintf("Ishchi %d ishni bajardi", id+1)
}
func main() {
var wg sync.WaitGroup
natijalar := make([]string, 3)
for i := 0; i < 3; i++ {
wg.Add(1)
go ishla(i, natijalar, &wg)
}
wg.Wait()
for _, n := range natijalar {
fmt.Println(n)
}
fmt.Println("Barcha ishchilar tugatdi")
}
Ishchi 1 ishni bajardi
Ishchi 2 ishni bajardi
Ishchi 3 ishni bajardi
Barcha ishchilar tugatdi
wg.Add(1) — har yangi goroutine boshlanishidan oldin hisoblagichni oshiradi. defer wg.Done() — goroutine tugaganda hisoblagichni kamaytiradi. wg.Wait() — hisoblagich nolga tushmaguncha, ya’ni barcha goroutine tugamaguncha, bloklanib turadi. Har bir ishchi o’z natijasini o’ziga tegishli natijalar[id] katagiga yozgani uchun, goroutine’lar qaysi tartibda tugashidan qat’iy nazar, yakuniy chiqish har doim tartibli bo’ladi.
Nega alohida katak muhim
Agar barcha goroutine bitta umumiy o’zgaruvchini birga o’zgartirsa (masalan, umumiy massivga navbatma-navbat qo’shsa), natija goroutine’lar qaysi tartibda tugashiga bog’liq bo’lib qoladi — bu tartib esa har ishga tushirishda boshqacha bo’lishi mumkin. Yuqoridagi misolda har ishchi faqat o’ziga ajratilgan natijalar[id] katagiga yozgani uchun, bunday tasodifiylikning oldi olingan — bu ataylab tanlangan, xavfsiz naqsh.
Goroutine’lar orasida ma’lumot almashish
Goroutine’lar mustaqil ishlaganda, ular orasida ma’lumot xavfsiz almashish kerak bo’ladi — buning standart vositasi channel, keyingi darsning mavzusi.