Learn Go: Introduction to Functions in Golang #11

An introduction to functions in Golang

Gopher

Lets go!!

Published · Jan 21 2020

In this tutorial, we are going to be looking at functions in Golang and hopefully, by the end of this tutorial, you will have a firm grasp as to what they are and how you can use them in your own projects.

We’ll be covering the following topics within this tutorial:
  • The basics on Function Declaration
  • Working with multiple return values

At the end of this tutorial, there will be challenges that you can attempt to complete on your own working machine that will help to validate what we have covered and give you a taste of writing your own functions in Go.
. . .

Functions

A function is an independent section of code that maps zero or more input parameters to zero or more output parameters.

Functions (also known as procedures or subroutines) are often represented as a black box: (the black box represents the function)


. . .

Function Syntax

The general syntax for declaring a function in go is
func functionname(parametername type) returntype { //function body }

The function declaration starts with a func keyword followed by the functionname. The parameters are specified between ( and ) followed by the returntype of the function.

The syntax for specifying a parameter is parameter name followed by the type. Any number of parameters can be specified like (parameter1 type, parameter2 type). Then there is a block of code between { and } which is the body of the function.

The parameters and return type are optional in a function. Hence the following syntax is also a valid function declaration.
func functionname() { //function body
}

. . .

Defining a Function

A function is defined by using the func keyword. This is then followed by a name of your choosing and a set of parentheses that hold any parameters the function will take (they can be empty). The lines of function code are enclosed in curly brackets {}.

In this case, we’ll define a function named hello():
func hello() {}

This sets up the initial statement for creating a function.

From here, we’ll add a second line to provide the instructions for what the function does. In this case, we’ll be printing Hello, World! to the console:
hello.go
func hello() { fmt.Println("Hello, World!") }

Our function is now fully defined, but if we run the program at this point, nothing will happen since we didn’t call the function.

So, inside of our main() function block, let’s call the function with hello():
package main

import "fmt"

func hello() {
fmt.Println("Hello, World!")
}

func main() {
hello()
}


Notice that we also introduced a function called main(). The main() function is a special function that tells the compiler that this is where the program should start.

Defining functions within a program makes our code modular and reusable so that we can call the same functions without rewriting them.
. . .

Working with Parameters

So far we have looked at functions with empty parentheses that do not take arguments, but we can define parameters in function definitions within their parentheses.

A parameter is a named entity in a function definition, specifying an argument that the function can accept. In Go, you must specify the data type for each parameter.

If you have a set of parameters that are all the same value, you can omit specifying the type each time. Let’s create a small program that takes in parameters x, y, and z that are all int values.

We’ll create a function that adds the parameters together in different configurations. The sums of these will be printed by the function. Then we’ll call the function and pass numbers into the function.
package main import "fmt" func main() { addNumbers(1, 2, 3) } func addNumbers(x, y, z int) { a := x + y b := x + z c := y + z fmt.Println(a, b, c) }


When we created the function signature for addNumbers, we did not need to specify the type each time, but only at the end.

We passed the number 1 in for the x parameter, 2 in for the y parameter, and 3 in for the z parameter. These values correspond with each parameter in the order they are given.

The program is doing the following math based on the values we passed to the parameters:
a = 1 + 2 b = 1 + 3 c = 2 + 3

When we pass 1, 2, and 3 as parameters to the addNumbers() function, we receive the expected output.

Parameters are arguments that are typically defined as variables within function definitions. They can be assigned values when you run the method, passing the arguments into the function.
. . .

Returning a Value

You can pass a parameter value into a function, and a function can also produce a value.

A function can produce a value with the return statement, which will exit a function and optionally pass an expression back to the caller. The return data type must be specified as well.

So far, we have used the fmt.Println() statement instead of the return statement in our functions. Let’s create a program that instead of printing will return a variable.

In a new text file called double.go, we’ll create a program that doubles the parameter x and returns the variable y. We issue a call to print the result variable, which is formed by running the double() function with 3 passed into it:
double.go
package main import "fmt" func main() { result := double(3) fmt.Println(result) } func double(x int) int { y := x * 2 return y }


We can run the program and see the output:
Output 6

The integer 6 is returned as output, which is what we would expect by multiplying 3 by 2.

If a function specifies a return, you must provide a return as part of the code. If you do not, you will receive a compilation error.

We can demonstrate this by commenting out the line with the return statement:
double.go
package main

import "fmt"

func main() {
result := double(3)
fmt.Println(result)
}

func double(x int) int {
y := x * 2
// return y
}


Now, let’s run the program again:
Output ./double.go:13:1: missing return at end of function

Without using the return statement here, the program cannot compile.

Functions exit immediately when they hit a return statement, even if they are not at the end of the function:
package main import "fmt" func main() { loopFive() } func loopFive() { for i := 0; i < 25; i++ { fmt.Print(i) if i == 5 { // Stop function at i == 5 return } } fmt.Println("This line will not execute.") }

Here we iterate through a for loop, and tell the loop to run 25 iterations. However, inside the for loop, we have a conditional if statement that checks to see if the value of i is equal to 5. If it is, we issue a return statement.

Because we are in the loopFive function, any return at any point in the function will exit the function. As a result, we never get to the last line in this function to print the statement This line will not execute..

Using the return statement within the for loop ends the function, so the line that is outside of the loop will not run. If, instead, we had used a break statement, only the loop would have exited at that time, and the last fmt.Println() line would run.

The return statement exits a function, and may return a value if specified in the function signature.
. . .

Returning Multiple Values

More than one return value can be specified for a function. Let’s examine the repeat.go program and make it return two values. The first will be the repeated value and the second will be an error if the reps parameter is not a value greater than 0:
package main

import "fmt"

func main() {
val, err := repeat("Sammy", -1)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(val)
}

func repeat(word string, reps int) (string, error) {
if reps <= 0 {
return "", fmt.Errorf("invalid value of %d provided for reps. value must be greater than 0.", reps)
}
var value string
for i := 0; i < reps; i++ {
value = value + word
}
return value, nil
}


The first thing the repeat function does is check to see if the reps argument is a valid value. Any value that is not greater than 0 will cause an error. Since we passed in the value of -1, this branch of code will execute. Notice that when we return from the function, we have to provide both the string and error return values. Because the provided arguments resulted in an error, we will pass back a blank string for the first return value, and the error for the second return value.

In the main() function, we can receive both return values by declaring two new variables, value and err. Because there could be an error in the return, we want to check to see if we received an error before continuing on with our program. In this example, we did receive an error. We print out the error and return out of the main() function to exit the program.

If there was not an error, we would print out the return value of the function.

Note: It is considered best practice to only return two or three values. Additionally, you should always return all errors as the last return value from a function.

Running the program will result in the following output:
Output invalid value of -1 provided for reps. value must be greater than 0.

In this section we reviewed how we can use the return statement to return multiple values from a function.
. . .

Conclusion

So, in this article we managed to cover quite a fair bit on functions within the go programming language. Hopefully, you found this useful! If you require any further help or assistance then please feel free to let me know in the comments section below!

. . .

. . .
References:

On a mission to build Next-Gen Community Platform for Developers