- Channels in GO allow communication between goroutines.
- Channels can only transmit data of a specified type.
- They can be viewed as pipes between goroutines.
- In program channelEx1.go, n is taken from the command line, e.g. go run channelEx1.go 5
/*channelEx1.go*/ package main import ("fmt"; "os"; "strconv") var done = make(chan bool) func routine1(p chan int, n int) { for i:=0; i<n; i++{ p <- i fmt.Println("routine 1 sent", i) s := <- p fmt.Println("routine 1 received", s) } close(p) fmt.Println("routine1 ended") done <- true } func routine2(p chan int) { for { v, open := <-p if !open { fmt.Println("routine2 ended") return } fmt.Println("routine 2 received", v) p <- v*v fmt.Println("routine 2 sent", v*v) } } func main() { n, _ := strconv.Atoi(os.Args[1]) p := make(chan int) go routine1(p, n) go routine2(p) <-done fmt.Println("main program ended") }
- A channel p is created on line 35 using the command make(chan int) This channel is bidirectional and can send or receive data of type int only.
- goroutine1 sends out the numbers 0 … n − 1 and then closes channel p.
- goroutine2 attempts to receive a value on channel p. It exits if p is closed; otherwise it sends back the square of the received value.
- done is a channel of type boolean (declared on line 6) used to signal the completion of goroutine1 (line 17).
- The main program waits for a value to be received on channel done (line 38) and then exits.
- The numbers and their squares are printed strictly in order. This ordering is imposed by the use of sends and receives on channels.
- Here is an example execution:
$ go run channelEx1.go 5 routine 1 sent 0 routine 2 received 0 routine 2 sent 0 routine 1 received 0 routine 1 sent 1 routine 2 received 1 routine 2 sent 1 routine 1 received 1 routine 1 sent 2 routine 2 received 2 routine 2 sent 4 routine 1 received 4 routine 1 sent 3 routine 2 received 3 routine 2 sent 9 routine 1 received 9 routine 1 sent 4 routine 2 received 4 routine 2 sent 16 routine 1 received 16 routine1 ended main program ended
The select Statement and Channels
- The select statement allows the execution of different actions depending on which channel has sent a message.
- The program channelEx2.go creates a server and three clients.
/*channelEx2.go*/ package main import ("fmt"; "os"; "strconv"; "math/rand"; "time") func client(c chan int, id int) { for {//infinite loop: //generates a random number between 0 and 9: num := rand.Intn(10) //sends it out on its channel: c <- num fmt.Printf("client %d sent %d\n", id, num) //wait for response from the server: val := <- c fmt.Printf("client %d rxed %d\n", id, val) //2 sec sleep to comfortably view progress: time.Sleep(2*time.Second) } } func server(ch0 chan int, ch1 chan int, ch2 chan int) { var n int for {//infinite loop: select {//action based on channel that sent message case n = <- ch0: fmt.Printf("Server rxed %3d from client 0\n", n) ch0 <- n*2 case n = <- ch1: fmt.Printf("Server rxed %3d from client 1\n", n) ch1 <- n*3 case n = <- ch2: fmt.Printf("Server rxed %3d from client 2\n", n) ch2 <- n*4 } } } func main() { seed, _ := strconv.Atoi(os.Args[1]) rand.Seed(int64(seed)) //Three channels are created: ch0 := make(chan int); ch1 := make(chan int); ch2 := make(chan int) //server goroutine created and passed the channels: go server(ch0,ch1,ch2) //Each client goroutine is passed a channel & id //(id for exposition only): go client(ch0,0); go client(ch1,1); go client(ch2,2) //servers & clients keep executing infinite loops //until "Enter" is pressed: fmt.Scanln() //"Enter" pressed: program & goroutines termininated fmt.Println("main program ended") }
Here is a typical output:
client 0 sent 6 Server rxed 6 from client 0 Server rxed 3 from client 2 client 2 sent 3 client 2 rxed 12 Server rxed 0 from client 1 client 1 sent 0 client 1 rxed 0 client 0 rxed 12 client 1 sent 3 Server rxed 3 from client 1 Server rxed 2 from client 2 client 2 sent 2 client 2 rxed 8 Server rxed 8 from client 0 client 1 rxed 9 client 0 sent 8 client 0 rxed 16 client 0 sent 2 Server rxed 2 from client 0 Server rxed 2 from client 1 client 1 sent 2 client 1 rxed 6 Server rxed 2 from client 2 client 2 sent 2 client 2 rxed 8 client 0 rxed 4 main program ended
Review
- Channels are a major feature of GO.
- They allow goroutines to communicate with each other in a straightforward fashion.