19

I am working with Go channels, and I was wondering what's the difference between closing a channel and setting it to nil?

Edit:

In this example, I would like to disconnect the sender and receiver by, whether closing the channel or setting to nil. What's the best practice to do this?

elmiomar
  • 1,747
  • 2
  • 17
  • 27
  • 1
    A channel value is like any other value. If there are no references to it, it will be garbage collected. Related / useful to know: [How does a non initialized channel behave?](http://stackoverflow.com/questions/39015602/how-does-a-non-initialized-channel-behave/39016004#39016004) – icza Apr 25 '17 at 17:08

3 Answers3

29

Setting a channel variable to nil simply sets the variable to nil, while leaving the channel it had previously referred to initialized.

It's the same as setting any other variable to nil.

If there are other references to the channel, you could still access it. If there are not, it will be garbage collected.

Additionally, nil versus closed channels behave differently when writing or reading. From Dave Cheney's blog post, Channel Axioms, which I recommend reading in its entirety:

  • A send to a nil channel blocks forever
  • A receive from a nil channel blocks forever
  • A send to a closed channel panics
  • A receive from a closed channel returns the zero value immediately
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
  • 2
    So, I understand that a good practice (maybe the best) is to close the channel. This way, even if there are other references to that channel I won't be able to use it and I will avoid memory leaks. (and this is exactly why I asked the question). Thanks for your reply! – elmiomar Apr 25 '17 at 16:49
  • Thank you all! That was really helpful. @Flimzy, indeed the blog post is very useful. – elmiomar Apr 25 '17 at 18:44
  • @Jonathan Hall, as i understand from LinkedIn course "Applied Concurrency in Go", section "channels", part "Closing channels": receive/send from/to Nil channel blocks not forever, but until channel is initialized, and value is available. – zzfima Jan 13 '23 at 12:38
  • 1
    @zzfima: Once you initialize it, it's no longer a nil channel. – Jonathan Hall Jan 13 '23 at 12:44
8

Another critical difference is with select:

  • a closed channel, will be selected immediately, and get nil value of the channel type.
    Thus may cause the other channels in the select never get selected.
  • a nil channel, will never be selected.
Eric
  • 22,183
  • 20
  • 145
  • 196
4

It's in a language specification. You can receive from closed channel forever, but writing on closed channel cause runtime panic. Both operation on a nil channel blocks forever. Such a behaviour commonly used in synchronization schemes.

Uvelichitel
  • 8,220
  • 1
  • 19
  • 36