Darsliklar Go Lang Channels

Go Lang Go Lang Channels

Channel — goroutine’lar orasida ma’lumot xavfsiz almashish uchun Go’ning o’rnatilgan vositasi. Channel orqali yuborilgan ma’lumot bir vaqtning o’zida faqat bitta goroutine’ga yetib boradi — bu umumiy xotirani qo’lda qulflashdan (Mutex) ko’ra tabiiyroq, xavfsizroq yechim.

channelmake(chan Tur) orqali yaratiladigan, ma’lum turdagi qiymatlarni goroutine’lar orasida uzatuvchi quvur. <- operatori yo’nalishga qarab yuborish yoki qabul qilishni bildiradi.

Yuborish va qabul qilish

package main

import "fmt"

func ishla(natija chan string) {
    natija <- "ish tugadi"
}

func main() {
    kanal := make(chan string)
    go ishla(kanal)

    xabar := <-kanal
    fmt.Println(xabar)
}
ish tugadi

natija <- "ish tugadi" — qiymatni kanalga yuboradi. <-kanal — qiymatni kanaldan qabul qiladi. Muhim xususiyat: buferlanmagan kanal (make(chan string), hajmsiz) yuboruvchi va qabul qiluvchi ikkalasi ham tayyor bo’lgunча bloklanadi — bu goroutine’lar orasida avtomatik sinxronlashtirish nuqtasi yaratadi, sync.WaitGroupga alohida ehtiyoj qoldirmasdan.

Buferlangan kanal

Kanal ma’lum sig’im bilan yaratilsa, yuborish darhol qabul qilinishini kutmasdan, bufer to’lmaguncha davom etaveradi:

package main

import "fmt"

func main() {
    kanal := make(chan int, 3)
    kanal <- 1
    kanal <- 2
    kanal <- 3

    fmt.Println(len(kanal), cap(kanal))

    fmt.Println(<-kanal)
    fmt.Println(<-kanal)
    fmt.Println(<-kanal)
}
3 3
1
2
3

make(chan int, 3) — 3 ta joyli bufer. Uchala qiymat ham hech kim qabul qilishini kutmasdan yuborildi. len(kanal) — hozir bufердаgi elementlar soni, cap(kanal) — umumiy sig’im. Qiymatlar qabul qilinganda, birinchi yuborilgani birinchi chiqadi (FIFO).

close va for…range — oqim tugaganini bildirish

Yuboruvchi tomon barcha ma’lumotni jo’natib bo’lgach, kanalni close bilan yopadi — qabul qiluvchi esa for...range bilan, kanal yopilguncha, avtomatik o’qiyveradi:

package main

import "fmt"

func sonlarYubor(kanal chan int) {
    for i := 1; i <= 5; i++ {
        kanal <- i
    }
    close(kanal)
}

func main() {
    kanal := make(chan int)
    go sonlarYubor(kanal)

    for son := range kanal {
        fmt.Println(son)
    }
}
1
2
3
4
5

close(kanal) — endi yangi qiymat kelmasligini bildiradi. for son := range kanal — kanal yopilib, undagi barcha qiymat qabul qilinguncha davom etadi, so’ng avtomatik to’xtaydi — alohida chiqish shartisiz.

Yopiq kanalni comma-ok bilan tekshirish

Yopilgan, bo’sh kanaldan qiymat olishga urinish xato bermaydi — zero value va false qaytadi:

package main

import "fmt"

func main() {
    kanal := make(chan int, 2)
    kanal <- 42
    close(kanal)

    v, ok := <-kanal
    fmt.Println(v, ok)

    v2, ok2 := <-kanal
    fmt.Println(v2, ok2)
}
42 true
0 false

Birinchi qabul — kanalda hali qiymat (42) bor edi, oktrue. Ikkinchisida kanal bo’sh va yopiq, shuning uchun zero value (0) va okfalse qaytdi. Bu — Map darsida ko’rgan comma-ok naqshining kanal uchun muqobili.