GoLang nil Channel

12-01-2020




Imgur



Go provides built-in support for concurrency. Channels in Go are a way to pass data between Go routines.



What are nil channels?

Nil channels are channels which have a nil value. With a nil channel, it won't be able to send nor receive values. This can prove useful when you want to block the process. When use with select statement, it can allow you to ignore the nil channel, because it won't be able to receive any value, therefore allowing the select statement to select other channel cases.

Below is an example of one use case of a nil channel:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// timeChannel is a channel that will receive current time after 2 seconds.
timeChannel := time.After(2000 * time.Millisecond)
// itemChannel is a nil channel. It won't be able to send or receive string.
var itemChannel chan string

var anItem string
sliceOfItems := []string{}
if len(sliceOfItems) > 0 {
  log.Println("sliceOfItems is not empty")

  // Initialise the itemChannel, so that now it can send and receive string.
  itemChannel = make(chan string)
  anItem = sliceOfItems[0]
  // Go routine to send anItem into itemChannel.
  go func() {
  	itemChannel <- anItem
  }()
}

select {
  case <-timeChannel:
    // Will run after 2 seconds.
    log.Println("select: <-timeChannel")
  case item := <-itemChannel:
    // Will run if sliceOfItems is not empty.
    log.Println("select: itemChannel <- anItem")
    log.Println("item:", item)
}

log.Println("DONE")

In the example, we've got 2 channels: timeChannel and itemChannel. timeChannel is a channel of type chan Time which after the specified time (2 seconds in the example) will receive the current time. itemChannel is a channel of type chan string and is use to send and receive string values.

The example, shows that itemChannel is initialised as a nil channel with var itemChannel chan string. When it's a nil channel, it won't be able to send nor receive string. It will however be made "un-nil" only when the slice: sliceOfItems is not empty, so that an item from the slice can be send into the channel.

When the example code is run, you'll see that only the timeChannel select case is run after 2 seconds. This is because the itemChannel is currently nil, and it can't send nor receive string, therefore it's blocked in the select statement. This allows the timeChannel to be selected after 2 seconds.

If you add an element to the slice: sliceOfItems, you'll see that the itemChannel is selected instead of the timeChannel.



Conclusion

I hope you've enjoyed this little snippets of code. This is only one of the many concurrency patterns for Go, and I encourage you to look into them, as will I.