A recent discussion on IRC about the value of returning anonymous functions via channels inspired this post. TLDR; it’s not a great idea to return functions this way, I personally will reject any pull request where someone has done this in the PR.
Go Channels are communication devices that allow goroutines to send information back and forth between each other. They are typed synchronised queues that will carry data of the type determined by the declaration (normally) between goroutines. There is no limit on what types a channel can be created to carry, however a great deal of care needs to be taken with one type in particular - anonymous functions.
// A channel that carries ints
ch := make(chan int)
There is little stopping someone from defining channels that carry anonymous functions
// A channel carrying anonymous functions
ch := make(chan func())
Why shouldn’t they be allowed in code then? Clearly the language designers felt that any type was able to be carried by a channel, and a function is a type after all.
A channel is relaying information between goroutines. If a function is returned then that function must be guaranteed to be thread safe, that is it must make safe concurrent use of restricted or contestable resources.
Because the function has come from another goroutine this restriction is an absolute must.
So, it might be tempting to say, ok, hand on heart the functions carried by this channel will always be threadsafe. And that might be the genuine intention. But time and multiple developers (even a forgetful single dev two days later) can make changes to the function being passed back, and there’s no way to check from the consumer end whether the restrictions have been adhered too.
A developer could come along - to fix a bug, or add a feature - and inadvertently add a problem (like change the function to become a closure on a contestable resource) and thus rely on code review to spot the potential bug.
In my opinion there’s no need to carry anonymous functions on channels, the channel should be carrying results from executing functions or acting as a semaphore and allowing a given goroutine to run a given function (which still ends up with a return channel only carrying the results of running the function). Therefore banning channels carrying functions is the sane and prudent approach to prevent potential catastrophes.