Go в примери: Затваряне на канали

Като затворим канал указваме, че няма да изпращаме повече стойности по него. Така уведомяваме получателите по този канал, че сме приключили.

package main
import "fmt"

В този пример ще използваме канала задачки, за да съобщим от гозадачата main() каква работа има за вършене на друга гозадача – работник. Когато нямаме повече задачки за работника, ще затворим канала задачки, с помощта на вградената функция close.

func main() {
    задачки := make(chan int, 5)
    готово := make(chan bool)

Ето я гозадачата работник. Тя получава многократно съобщения по канала задачки чрез изявлението з, още := <-задачки. При този особен вид получаване с две стойности, стойността в променливата още ще бъде false, ако каналът задачки е затворен и всички стойности от канала вече са получени. Използваме този прийом, за да уведомим главната гозадача по канала готово, че сме обработили всички задачки.

    go func() {
        for {
            з, още := <-задачки
            if още {
                fmt.Println("получих задачка", з)
            } else {
                fmt.Println("получих всички задачки")
                готово <- true
                return
            }
        }
    }()

Чрез това повторение изпращаме три задачки по канала задачки и след това го затваряме.

    for з := 1; з <= 3; з++ {
        задачки <- з
        fmt.Println("изпратена задачка", з)
    }
    close(задачки)
    fmt.Println("изпратени са всичи задачки")

Чакаме работника с помощта на канала за съгласуване1. Този способ за съгласуване го разгледахме вече.


  1. synchronization – съгласуване
    <-готово

Четенето от затворен канал успява незабавно, като връща нулевата стойност на основния вид данни за този канал. Незадължителната втора върната стойност е true, ако получената стойност е доставена чрез успешно действие за изпращане по канала, или false, ако получената нулева стойност е такава, защото каналът е вече затворен и празен.

    оз, имаОще := <-задачки
    fmt.Println("има още задачки:", оз, имаОще)
}
$ go run closing-channels.go
изпратена задчка 1
изпратена задчка 2
изпратена задчка 3
изпратени са всичи задачки
получих задачка 1
получих задачка 2
получих задачка 3
получих всички задачки
има още задачки: 0 false

Мисълта за затворени канали ни води естествено към следващия ни пример – обхождане на канали с помощта на range.

Следващ пример: .