Go Functions (Part 2) — Saving functions in variables
Variables are not just used for storing integers, strings, boolean…etc, they can also store functions. These variables can then be used to call that function and feed arguments to it.
This article is part of the Functions in Go series.
Here’s an example where we stored a function called add2NumbersTogether inside a variable called add:
Line 14: We’ve saved the add2NumbersTogether function to a variable called add.
Line 15: From the output, we can see that the datatype for add is func(int, int) int
. The (int, int) int
bit is referred to as the function signature.
Line 16: When a variable is holding a function, you can invoke that function by adding round brackets after the variable. These round brackets are also used for passing the required arguments to the function.
This is a bit of a trivial example, where we didn’t like the function name “add2NumbersTogether”, and we used the functions-in-variables technique to create an alias for it called, “add”.
Function Signatures
In a lot of programming languages, variables belong to a particular “data type” (e.g. strings, integers,…etc). However, in Go, a variable can store more than just the traditional data types. That’s why we refrain from using the “data type” terminology and instead opt for the broader term, “type”. When it comes to storing functions in variables, it’s important to keep in mind of the following:
When a variable stores a function, then its type is defined as a function with a specific function signature.
The function signature refers to the function’s combination of input+output parameters. This function signature is treated like it’s very own type. That mean’s we can declare a variable with a function-based type, like in the following example. This is the same last example but we’ve now declared the variable first (line 14):
Updating function-type Variables
We can update regular variables from one value to another using the assignment operator, =
, as long as the values are of the same type. The same is also true for function type variables.
Here the variable, formula, initially stores the function, addition (line 19), and then we replaced the function with a different, multiplication (line 25).
This only works as-long-as the new function has a matching function signature since the function signature is part of the type specification (line 21).
Saving Anonymous Functions to Variables
Anonymous Functions are often saved to variables. I’ve written an article about Anonymous Functions already so I won’t go into too much detail here. But here’s a brief of this in action:
Passing functions into other functions
Since variables are used for passing arguments into functions, it means that we can pass a whole function into another function!!! Here’s an example:
Line 12: This complicated-looking line says that this function has 3 input parameters and no output parameters, the first parameter is named as “calculation” and accepts a function of the type func(int, int) int
. The “addition” function (line 7) has a matching function signature.
Line 19: We pass in a function in the form of the “add” variable into the formula function.
Tip: We can actually delete line 18, and rewrite line 19 to formula(addition, 2, 6)
and it’ll still work.
I find code written in this way is harder to read (especially line 12). That’s why I tend to avoid this approach where possible. However, it’s important to be aware of it, just in case you come across other peoples code written like this.
Returning Functions from other Functions
In a similar vein to passing functions in, you can also set up a function to return a function via its output parameter. Here’s an example:
Once again, I’m not a fan of writing code this way. I find it makes code harder to read.