Function Declaration
Declaring functions in Go is very straightforward. In fact, we have already declared a function in all of our programs so far. The main
function is required in every binary executable (a program we want to run on its own, not a library we want to share). As with loops and conditional statements, we need to follow the "one true brace style."
package main
import "fmt"
func main() {
fmt.Println("We are finally talking about functions!")
}
Let's go ahead and declare a more complicated function outside of main. add
will take two integers and return an integer.
package main
import "fmt"
func add(x, y int) int {
return x + y
}
func main() {
sum := add(2, 3)
fmt.Println("The sum of 2 + 3 is", sum)
}
func add
With the keywordfunc
we are telling the Go compileradd
is a function.(x, y int)
In the parentheses we are declaring the names of our parametersx
andy
. We also need to tell the compiler what type of arguments to expect. Here we are saying the arguments should both be of typeint
. We could alternatively declare each parameter type like this:func add(x int, y int)
.int {
After our list of parameters we need to declare what type of dataadd
will return, in this caseint
. If we don't return anything in function we leave this part blank ex)func printLine(msg string) {
return x + y
In our function body we return the value of x and y added.
NOTE: There is no implicit return like in Ruby.
Returning
In Go you can return multiple values!
func addAndSubtract(x, y int) (sum, difference int) {
sum = x + y
difference = x - y
return sum, difference
}
Here we are still taking two int
s, but now we are returning their sum and their difference! Note the use of parentheses when we return more than one value (this is necessary). In this example we can also see that Go allows us to name our return values; though, it is not necessary. We could have alternatively written this: func addAndSubtract(x, y int) (int, int)
. When we name our return values they are initialized to their zero value (we don't need to explicitly initialize them in our function body).
NOTE: It is important to remember that although we can always return any number of values in Go, this functionality should not be abused as it can lead to avoidable complexity.
First Class Functions
Go functions are first class. This means you can assign them to variables, send them as arguments to other functions, and even return functions. There are also function literals in Go AKA anonymous functions, as well as closures. JavaScript developers should feel right at home with this functionality.
package main
import "fmt"
func addNumber(number int) func(int) int {
return func(num int) int {
return number + num
}
}
func main() {
add42 := addNumber(42)
fmt.Println(add42(10)) //prints 52
}
This example demonstrates how to write a function literal, return a function, assign it to a variable, and create a closure. Let's go through the code step-by-step.
func addNumber(number int) func(int) int {
We are declaring our functionaddNumber
here. It will take an argument called number of type int andaddNumber
will return a function. It may seem superfluous, but we must tell the Go compiler what kind of function addNumber will return.func(int) int
is simply the type signature for the function we are going to return. The function we are returning will take anint
as a parameter and return anint
value.return func(num int) int {
This is where we are returning our anonymous function (called a function literal in Go). It will take anint
as an argument and return anint
value.return number + num
We are simply returning the parent function'snumber
argument added to the function literal's argumentnum
.add42 := addNumber(42)
Here we are assigning the return value of addNumber (our function literal) and assigning it to the variableadd42
.add42
now points to a function that will add whatever number we pass it with 42 because that was the number we passed to addNumber when we initializedadd42
. This is where the closure is created.
Simplifying With Custom Types
In a statically typed language we need to tell our compiler what kind of data our variable should hold. Go has a number of built-in basic types such as int
, float
, bool
, and string
, but we can also declaring our own types! This will make our last example a little cleaner. Enter another reserved word: type
!
package main
import "fmt"
type addClosureFunc func(int) int
func addNumber(number int) addClosureFunc {
return func(num int) int {
return number + num
}
}
func main() {
add42 := addNumber(42)
fmt.Println(add42(10)) //prints 52
}
It is extremely simple to declare a new type. You simply need a name for the type: addClosureFunc
and the underlying implementation func(int) int
. We can even add names to our parameter and return value if we want, just to make things a little more clear.
type addClosureFunc func(sum int) (num int)
Conclusion
With the power to declare functions, pass them around like any other variable, and create our own types, we can really see the power Go gives us to create very maintainable, easy-to-follow code. Next week we will talk about methods.
Top comments (0)