Go / Channel үндэс

Channel үндэс

Өмнөх хичээлд goroutine-үүд нэгэн зэрэг ажиллаж болохыг сурсан. Гэхдээ тэдгээр нь хоорондоо хэрхэн ярилцах вэ? Энд channel орж ирнэ. Channel нь горутинүүдийн хооронд өгөгдөл дамжуулах "хоолой" юм.

Go-ийн алдарт хэлц: "Санах ойг хуваалцан харилцахын оронд харилцан ярилцаж санах ойг хуваалц."

Channel үүсгэх ба ашиглах

Channel-ийг make ашиглан үүсгэнэ. <- оператор нь өгөгдөл илгээх болон хүлээн авахад ашиглагддаг:

go
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-ийн хамгийн чухал онцлог: илгээгч хүлээн авагчийг хүлээдэг, хүлээн авагч илгээгчийг хүлээдэг.

go
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-ийн чиглэлийг тодорхойлж болно:

go
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 байна:

go
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-ийн ахисан хэрэглээ маш хүчирхэг хэрэгсэл юм.