Channel үндэс
Өмнөх хичээлд goroutine-үүд нэгэн зэрэг ажиллаж болохыг сурсан. Гэхдээ тэдгээр нь хоорондоо хэрхэн ярилцах вэ? Энд channel орж ирнэ. Channel нь горутинүүдийн хооронд өгөгдөл дамжуулах "хоолой" юм.
Go-ийн алдарт хэлц: "Санах ойг хуваалцан харилцахын оронд харилцан ярилцаж санах ойг хуваалц."
Channel үүсгэх ба ашиглах
Channel-ийг make ашиглан үүсгэнэ. <- оператор нь өгөгдөл илгээх болон хүлээн авахад ашиглагддаг:
package main
import "fmt"
func main() {
// int төрлийн channel үүсгэх
ch := make(chan int)
// Горутин дотор утга илгээх
go func() {
ch <- 42 // channel руу 42 илгээж байна
}()
// Үндсэн горутин хүлээн авна
value := <-ch
fmt.Println("Хүлээн авсан утга:", value)
}
ch <- 42 нь "42-ийг ch channel руу илгээ" гэсэн утгатай.
value := <-ch нь "ch channel-аас утга хүлээн ав" гэсэн утгатай.
Channel-ийн блоклох шинж чанар
Channel-ийн хамгийн чухал онцлог: илгээгч хүлээн авагчийг хүлээдэг, хүлээн авагч илгээгчийг хүлээдэг.
package main
import (
"fmt"
"time"
)
func producer(ch chan string) {
fmt.Println("Илгээгч: бэлтгэж байна...")
time.Sleep(500 * time.Millisecond)
ch <- "бэлэн болсон өгөгдөл"
fmt.Println("Илгээгч: илгээлээ")
}
func main() {
ch := make(chan string)
go producer(ch)
fmt.Println("Хүлээн авагч: хүлээж байна...")
msg := <-ch // producer илгээтэл энд зогсоно
fmt.Println("Хүлээн авагч:", msg)
}
<-ch дээр үндсэн горутин producer функц утга илгээтэл хүлээнэ. Энэ нь time.Sleep ашиглахгүйгээр синхрончлол хийх боломж олгодог.
Channel-ийн чиглэл
Функцийн параметрт channel-ийн чиглэлийг тодорхойлж болно:
package main
import "fmt"
// Зөвхөн илгээх channel (send-only)
func send(ch chan<- int, value int) {
ch <- value
}
// Зөвхөн хүлээн авах channel (receive-only)
func receive(ch <-chan int) int {
return <-ch
}
func main() {
ch := make(chan int)
go send(ch, 99)
result := receive(ch)
fmt.Println("Үр дүн:", result)
}
chan<- int — зөвхөн илгээх боломжтой.
<-chan int — зөвхөн хүлээн авах боломжтой.
Энэ нь кодын аюулгүй байдлыг нэмэгдүүлдэг — функц channel-г буруу ашиглахад compile алдаа гарна.
Channel хаах
Илгээгч channel-ийг хааж болно. Хаасны дараа хүлээн авагч мөн утга авч болох боловч ok нь false байна:
package main
import "fmt"
func generate(ch chan int) {
for i := 1; i <= 5; i++ {
ch <- i
}
close(ch) // channel хаах
}
func main() {
ch := make(chan int)
go generate(ch)
// Channel хаагдтал утга авсаар байх
for value := range ch {
fmt.Println("Авсан:", value)
}
fmt.Println("Channel хаагдлаа")
}
for value := range ch нь channel хаагдтал автоматаар утга авсаар байдаг. Хаагдсаны дараа loop дуусна.
Дараагийн хичээлд:
Buffered channel, нэг channel-аас олон горутин хүлээн авах, ажилчдын (worker pool) хэв маягийг судална. Channel-ийн ахисан хэрэглээ маш хүчирхэг хэрэгсэл юм.