Concurrency means multiple process happening simultaneously. In Go the concurrency is achieved using goroutines and channels.
In Go every concurrently executing activity is known as goroutines. For now, you can assume that a goroutine is similar to a thread in other languages. Here we create the goroutines by using the keyword go followed by a function invocation:
f() // call f(); wait for it to return go f() // create a new goroutine that calls f(); don't wait
Whenever we invoke a function in our program it will execute all the statements in that function and then return to the next line following the invocation. But with goroutine we can return immediately to the next line without waiting for the function to complete.
Program Example :
package main import "fmt" func f(num int) { for i := 0; i < 5; i++ { fmt.Println(num, ":", i) } } func main() { go f(0) var input string fmt.Scanln(&input) }
The above program consists of two goroutines. The first one is implicit and it is the main function itself. The second one is created when we call go f(0).
Goroutines are lightweighted so we can easily create thousands of them.
Example (Modifying the above example to run 10 goroutines)
func main() { for i := 0; i < 10; i++{ go f(i) } var input string fmt.Scanln(&input) }
Channels is used to provide a way for two goroutines to communicate with one another and synchronize their execution i.e the channels are the connections between goroutines.
A channel is communication system which helps one goroutine to send values to another goroutine.
Each channel is a pipe for values of a particular type called channel’s element type. For example, chan int (Here int is the type of the things that are passed on this channel).
Creating a channel
ch :=make(chanint) // ch has type 'chan int'
A channel has two primary operations, send and receive which are collectively known as communications. The left arrow <-operator is used to send and receive messages on the channel. In send operation statement this <-left arrow is used to separate the channels and the value operands. In receive operation statement the arrow precedes the channel operand.
ch <-x // a sendstatement x=<-ch // a receive expression in an assignment statement <-ch // a receive statement; result is discarded
Another operation supported by the channels is close which is used to set that no more values will ever be sent through this channel. Here to close the channel the built function close(channel_name) is used.
close(ch)
Creating a channel with a simple call to make,is called an unbuffered channel. Here the make, hasthe optional second argument, an integer called the channel’s capacity. If the make statement carries the nonzero value as the capacity, then the make creates a buffered channel.
ch = make(chanint) // unbuffered channel ch = make(chanint, 0) // unbuffered channel ch = make(chanint, 3) // buffered channel with capacity 3
Go has a special statement called select which works similarly like a switch but only channels. Combining goroutines and the channel is one of the main feature of Go.
Program Example :
func main() { c1 := make(chan string) c2 := make(chan string )go func() { for { c1 <-"from 1" time.Sleep(time.Second * 1) } }() go func() { for { c2 <-"from 2" time.Sleep(time.Second * 2) } }() go func() { for { select { case msg1 := <-c1: fmt.Println(msg1) case msg2 := <-c2: fmt.Println(msg2) } } }() var input stringfmt.Scanln(&input) }
Here this program prints “from 1” for every1 second and “from 2” for every 2 seconds. And the select option here will choose the first channel which is ready and receives from it (or sends to it). In case more than one channels are ready then it randomly chooses which one to receive from. Suppose none of the channels are ready then the statement blocks until one becomes available. The select statement is often used to implement a timeout.Like the switch statement, Select also has default case happens immediately if none of the channels are ready.
Progrm Example :
select { case msg1 := <-c1: fmt.Println("Message from 1", msg1) case msg2 := <-c2: fmt.Println("Message from 2", msg2) case <-time.After(time.Second): fmt.Println("timeout") default:fmt.Println("No one is ready") }
All Rights Reserved. © 2024 BookOfNetwork