Go: práce s kanály

Jednou ze skvělých věcí na Go jsou gorutiny, pomocí kterých zajišťuje concurrency. A aby vše fungovalo jak má, potřebujete nějak synchronizovat zpracovávaná data mezi jednotlivými gorutinami.

A právě k tomu se hodí kanály, channels. Kanály jsou jeden z prostředků jazyka, jak řídit flow mezi rádoby paralelně prováděnými částmi aplikacemi, gorutinami.

Díky kanálům pak můžete naplnit jeden z konceptů Go Do not communicate by sharing memory; instead, share memory by communicating.

A věřte nebo ne, i na úrovni práce s channels pak najdete nějaké návrhové vzory:

Fan out

Z jednoho vstupního kanálu multiplikujete výstup do více výstupních kanálů:

func Fanout(In <-chan int, OutA, OutB, OutC chan int) {
	for data := range In {
		select {
		case OutA <- data:
		case OutB <- data:
		case OutC <- data:
		}
	}
}

Fan In

Spojujete více vstupních kanálů do jednoho výstupního.

func fanIn(input1, input2 <-chan string) <-chan string {
	c := make(chan string)
	go func() {
		for {
			select {
			case s := <-input1:
				c <- s
			case s := <-input2:
				c <- s
			}
		}
	}()
	return c
}

Closing channel

Closing a channel indicates that no more values will be sent on it. This can be useful to communicate completion to the channel’s receivers

package main

import "fmt"

func main() {
	jobs := make(chan int, 5)
	done := make(chan bool)

	go func() {
		for {
			j, more := <-jobs
			if more {
				fmt.Println("received job", j)
			} else {
				fmt.Println("received all jobs")
				done <- true
				return
			}
		}
	}()

	for j := 1; j <= 3; j++ {
		jobs <- j
		fmt.Println("sent job", j)
	}
	close(jobs)
	fmt.Println("sent all jobs")

	<-done
}

Ve zkratce...

Uvedl jsem 3 asi nejpoužívanější channles návrhové vzory. Nicméně představivosti se meze nekladou a je jen na vás, jak skrze kanály zajistíte flow control vaší aplikace.

Další info najdete přímo na Golang blogu.