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.
channel —
make(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, ok — true. Ikkinchisida kanal bo’sh va yopiq, shuning uchun zero value (0) va ok — false qaytdi. Bu — Map darsida ko’rgan comma-ok naqshining kanal uchun muqobili.