Go в примери: Работилници

В този пример ще видим как се осъществява работилница1 с помощта на гозадачи и канали.


  1. worker pool – (за целите на превода) работилница – място, където работят множество работници
package main
import (
    "fmt"
    "time"
)

Ето я заготовката за работник, от която ще създадем няколко съработни1 единици2. Тези работници ще получават работа, по канала работа и ще изпращат произведенията си по канала произведено. Ще накараме всяка гозадача да заспи за секунда, за да наподобим времеемка, сиреч скъпоструваща задача.


  1. concurrent – съработен, едновременно работещ (буквално: съ-бягащ, от con (съ) + фр. courrir), съревновател, състезател
  2. instance – единица, инстанция
func работник(id int,
    работа <-chan int, произведено chan<- int) {
    for j := range работа {
        fmt.Println("работник", id, "започна задача", j)
        time.Sleep(time.Second)
        fmt.Println("работник", id, "завърши задача", j)
        произведено <- j * 2
    }
}
func main() {

За да ползваме нашата работилница с работници, трябва да им изпратим задачи и да съберем произведенето от всеки работник. За целта правим (make) два канала.

    const бройЗадачи = 5
    задачи := make(chan int, бройЗадачи)
    произведено := make(chan int, бройЗадачи)

Тук създаваме три работника, които в началото не работят, защото все още нямат задачи.

    for w := 1; w <= 3; w++ {
        go работник(w, задачи, произведено)
    }

Тук изпращаме пет задачи и после затваряме с помощта на close канала, за да кажем, че това е всичко, което искаме да се изработи.

    for j := 1; j <= бройЗадачи; j++ {
        задачи <- j
    }
    close(задачи)

Накрая събираме всичко произведено. Това изявление също така обезпечава приключването на всички гозадачи-работници. Иначе програмата би завършила без да чака работниците. Друг начин да чакаме множество гозадачи е като си създадем чакалня[^wgroup] с помощта на WaitGroup. [^wgroup]: wait-group – (за целите на превода) чакалня, иначе – изчакване на множество гозадачи.

    for a := 1; a <= бройЗадачи; a++ {
        произведение := <-произведено
        fmt.Println("Произведено:", произведение)
    }
}

Работещата ни програма показва, че петте задачи биват извършвани от различни работници Програмата се изпълнява само за 2 секунди и нещо, макар всяка задача да отнема по секунда и нещо. За 2 секунди е свършена работа, отнемаща общо над 5 секунди, защото трите работника работеха едновременно.

$ time go run worker-pools.go
работник 3 започна задача 1
работник 1 започна задача 2
работник 2 започна задача 3
работник 2 завърши задача 3
работник 2 започна задача 4
Произведено: 6
работник 1 завърши задача 2
работник 1 започна задача 5
Произведено: 4
работник 3 завърши задача 1
Произведено: 2
работник 1 завърши задача 5
Произведено: 10
работник 2 завърши задача 4
Произведено: 8
real    0m2,232s

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