Take this example -
func funcB() { fmt.Println("Hi") })
funcA(funcB)
Is funcA receiving a pointer to funcB? Or is it receiving a full-blown immutable function?
So, if I execute this code -
func funcA() { fmt.Println("Hi") })
funcB(funcA)
funcC(funcA)
funcD(funcA)
funcE(funcA)
funcF(funcA)
are all of the function calls creating a new funcA object, or are all of them receiving the same pointer to funcA?
Functions hold no state to be passed either by value or by reference, i.e., they are just executable code. When you pass a function to another function, you are giving some reference to the executable code of the function's body.
How about anonymous functions?
You can also store an anonymous function or closure into a
func()value. In this case, your question becomes more interesting because closures can hold state.Is a closure passed to a function provided by value or by reference?
Running the code above outputs:
We can conclude that the closure's state – i.e., the captured
ivariable – is somehow being shared between calls tocall(). In principle, this behavior could have been achieved by:To find out how the closure captures its environment, we can change the value of
iinmain()and see whether theivalue that the closure sees gets affected. If we append the code below tomain():Then,
100is displayed. Therefore,iis shared betweenmain()and the closure (i.e., the closure doesn't have its own copy ofi). So, closures capture their environment by reference (we can now rule out the 2. option above).At this point, we still haven't found whether a closure is passed by value or by reference. However, we already know that a closure's captured state is, in effect, passed by reference to functions because a closure holds references to the captured state. This is very likely the most critical insight.
Even so, we can see closures are passed by value:
Conclusion
Functions are just code. They don't store state. A function is a memory address to some executable code. When you pass a function to another function, you are giving this address.
Anonymous functions or closures can hold state that corresponds to the enclosing environment. Even though closures are passed by value, the states they hold are references to the environment they captured. So, the net effect is that the closure's captured environment is passed by reference.