Why not functional programming in Go?
To provide a holistic view of how FP can help us, as Go programmers, we should also consider when not to use FP. I view FP as a tool in my toolbox and when a problem lends itself to it, I will gladly use it – but just as importantly, we have to recognize when this does not work.
One of the concerns around FP is performance – while there is a lot to say on this topic, as we’ll see in later chapters, performance concerns could mean we throw out some functional concepts such as immutability in favor of executing with speed. This is more complex than it might sound at first, as Go pointers are not guaranteed to be faster than Go’s pass-by-value functions. We’ll expand more on the performance concerns in later chapters.
Another reason not to choose FP is Go’s lack of tail-call optimization. In theory, every loop you write in your program could be replaced by a recursive call, but as of Go 1.18, Go does not have the necessary tools to do this efficiently and you’d risk running into stack overflows. There are ways around this, as we will see, but if it starts sacrificing performance or readability significantly, my advice would be to just write a loop. This is not to say recursion is never the right approach. If you’ve worked with trees or graphs extensively, you’ve probably written some recursive algorithms and found them to work just fine.
Finally, if you are working on an existing code base with many other contributors, the best thing to do is follow the style of the code base. While some concepts of FP can be introduced quite easily, it is harder to enforce them in a team that’s not on board with the whole idea. Luckily, many programmers today see benefits in key concepts of FP. Even in Java or C#, the idea of immutable code is embraced. Side effects similarly are more and more seen as unwanted.
Let’s embrace Go as a fully multi-paradigm language and leverage each paradigm where it makes sense.