Kanallar orqali ma'lumot almashish
Go dasturlash tilida kanal (channel) — bu turli goroutinelar o'rtasida xavfsiz ma'lumot almashish va ularni sinxronlashtirish vositasidir.
Go falsafasida mashhur qoida bor: "Xotirani ulashish orqali aloqa qilmang, balki aloqa qilish (kanallar) orqali xotirani ulashing".
make())Kanal yaratish uchun o'rnatilgan make() funksiyasidan va chan kalit so'zidan foydalaniladi:
ch := make(chan int)
Bu yerda chan int ushbu kanal faqat butun son (int) turidagi ma'lumotlarni o'tkazishini bildiradi.
package main
import "fmt"
func main() {
number := make(chan int)
fmt.Printf("Kanal turi: %T\n", number)
fmt.Printf("Kanal manzili: %v\n", number)
}
Natija:
Kanal turi: chan int
Kanal manzili: 0xc00007a060
<-)Kanalga ma'lumot yuborish va undan qabul qilib olish uchun strelka <- operatori ishlatiladi:
kanalNomi <- ma'lumot
Masalan: number <- 15
qabul_qilingan := <-kanalNomi
yoki to'g'ridan-to'g'ri chop etish: fmt.Println(<-kanalNomi)
package main
import "fmt"
func channelData(number chan int, message chan string) {
// Kanallarga ma'lumot uzatamiz
number <- 15
message <- "Go Kanallarini o'rganish"
}
func main() {
// Kanallarni yaratamiz
number := make(chan int)
message := make(chan string)
// Goroutineni ishga tushiramiz
go channelData(number, message)
// Kanallardan ma'lumotni qabul qilib olamiz
fmt.Println("Raqam:", <-number)
fmt.Println("Xabar:", <-message)
}
Natija:
Raqam: 15
Xabar: Go Kanallarini o'rganish
Goda oddiy kanallar sinxron (to'xtatuvchi/bloklovchi) xususiyatga ega:
package main
import "fmt"
func sendData(ch chan string) {
// Ma'lumot qabul qilinmaguncha keyingi qatorga o'tmaydi
ch <- "Jo'natildi! Qabul qilish muvaffaqiyatli bo'ldi"
fmt.Println("sendData(): Xabar yetkazildi!")
}
func main() {
ch := make(chan string)
go sendData(ch)
// Kanaldan ma'lumotni qabul qilamiz
fmt.Println("main():", <-ch)
}
Natija:
main(): Jo'natildi! Qabul qilish muvaffaqiyatli bo'ldi
sendData(): Xabar yetkazildi!
Ushbu bloklanish xususiyati tufayli main() funksiyasi goroutine o'z ishini tugatishini hech qanday time.Sleep()larsiz aniq va ishonchli kutib turadi.
package main
import "fmt"
func receiveData(ch chan string) {
// Kanaldan ma'lumot keladi
fmt.Println(<-ch)
}
func main() {
ch := make(chan string)
go receiveData(ch)
fmt.Println("Ma'lumot yo'q. Qabul qilish bloklangan.")
// Kanalga ma'lumot yuboramiz
ch <- "Ma'lumot qabul qilindi. Qabul qilish muvaffaqiyatli bo'ldi"
}
Natija:
Ma'lumot yo'q. Qabul qilish bloklangan.
Ma'lumot qabul qilindi. Qabul qilish muvaffaqiyatli bo'ldi
Bu yerda main() funksiyasi kanalga ma'lumot yuborishdan oldin receiveData() goroutinesini chaqiradi. Kanal hali ma'lumot olmagani uchun avval "Ma'lumot yo'q..." xabari chiqadi, so'ng kanal ma'lumotni yuborgach, receiveData() uni qabul qilib chop etadi.