Example Using a Channel and Goroutines¶
Code¶
package main
func main() {
/***** Creating a channel and a map *****/
/* We are creating 2 channels, one for sending and one for receiving. */
c, out := make(chan int), make(chan int)
/* The map */
m := map[int]int{1: 2, 3: 4}
for i, v := range m {
go func() {
<-c
out <- i + v
}()
}
close(c)
/* Printing to stderr with the builtin `println` function. */
println(<-out + <-out)
}
Output¶
14
Explanation¶
This Go code snippet demonstrates the use of goroutines, channels, and maps to perform concurrent computations and communicate the results via channels.
Line by Line¶
- This line declares the package name for the current file.
- Every Go file belongs to a package, and
package mainis special because it defines a package that can be compiled and executed.
- Every Go file belongs to a package, and
- This line defines the
mainfunction, which is the entry point of a Go program.- The Go runtime calls this function when the program starts.
- This line declares two variables,
candout, each initialized to a new channel of typeint.- The
make(chan int)function creates a new channel for transmitting integers. - Channels are a typed conduit through which you can send and receive values with the channel operator,
<-.
- The
-
Here, a map
mis declared and initialized.-
Maps are key-value data structures, and this particular map has both keys and values of type
int. -
The map is initialized with two key-value pairs:
1:2and3:4.
-
- This
forloop iterates over each entry in the mapm.- The
rangekeyword is used to iterate over elements in a variety of data structures. - For maps, it returns two values: the key and the value of the current element.
- These are assigned to variables
i(the key) andv(the value) for each iteration.
- The
-
This line starts a goroutine, which is a lightweight thread managed by the Go runtime.
- The
gokeyword precedes the function call to run the function concurrently. - The function being called is an anonymous function (a function without a name), defined right there.
- The
- This line is a blocking receive operation on the channel
c.- The goroutine waits until it can receive a value from
c. - However, since no value is ever sent on
candcis closed before any receive operation, this operation proceeds immediately without retrieving any value due to the channel being closed.
- The goroutine waits until it can receive a value from
- This line sends the sum of
iandvinto theoutchannel.i + vcomputes the sum of the key and value from the map entry being iterated over in the loop.
- These characters end the anonymous function declaration and immediately invoke it.
- The
()at the end calls the function right after defining it.
- The
- This line closes the channel
c.- Closing a channel indicates that no more values will be sent on it.
- Receivers can still receive values previously sent on the channel.
- In this context, closing
callows the blocked receive operations in the goroutines to proceed.
- This line receives two values from the
outchannel, adds them together, and prints the result.- The
<-outoperation receives a value fromout. - Since there are two goroutines each sending a computed sum to
out, this line adds those two sums. - The order of the values received from
outis not deterministic because goroutines run concurrently.
- The
Other Info¶
-
Concurrency is the composition of independently executing processes, while parallelism (not demonstrated here) is the simultaneous execution of (possibly related) computations.
-
Non-Determinism: The values read from
outdepend on the order in which goroutines execute, which is non-deterministic.- So, the program can produce different outputs on different runs.
- Channel Closing: Closing a channel is a signal that no more values will be sent on it.
- Important: Only close a channel from the sender side and to ensure no more sends will happen; otherwise, the program will panic.
-
Deadlock Potential: If not careful, concurrent programs can deadlock.
-
In this case, there's no deadlock because the main goroutine waits for values from
out, and each of the spawned goroutines sends a value toout. -
However, if the logic were changed such that not enough values were sent on
out, the program would deadlock waiting on those values.
-