Master Go with functions

Anil Vedala
Level Up Coding
Published in
4 min readAug 10, 2020

--

By Renée French (http://reneefrench.blogspot.com)

Functions are first-class citizens in Go. They are everywhere. Functions can be added to struct types. They can be passed as parameters inside of a function, or functions can even be returned from another function. As functions are so ubiquitous in Go, it is essential to have a clearer understanding of the different forms of usage in order to master the language. Here in this article, I’ve detailed the structure of functions and their different use cases.

Starting with the syntax

In any language, a function comprises of the following entities — a keyword, name of the function, list of parameters, and a return type. Go also has the same entities -

func <func-name>(list of parameters) <comma-separated return types>{
<body>
<return stmts>
}

Here is an example of a simple function that adds two numbers and returns the value of addition —

Above function is invoked like this — addNumbers(2,3).

Go has an interesting feature in regards to passing parameters into a function. When the data type of a group of parameters is the same, they can be grouped and followed by a single data type keyword. For example, the above function has first and second parameters with the same int type. They can be grouped into one in the below manner —

Functions can be anonymous too. These functions can be invoked from the point of definition or they can be assigned to a variable and can be used later. Yes, functions can be assigned to variables. The same addNumbers() can be anonymized like this —

The above declaration can be used only once. We pass on the parameters at the time of the declaration itself. To be able to reuse the same anonymous function, we can assign the function to a variable as follows -

Higher-order functions

One might wonder about the need for anonymous functions. Go has support for higher-order functions ie. functions that accept other functions as parameters. Anonymous functions are used to pass into higher-order functions as params. Let us have a look at one of such functions.

In the above example, add and multiply are two anonymous functions that take in two int parameters and return the same int type. The acceptFunctionAndExecute is a higher-order function that accepts any other function that supports two int parameters and a result of type int. We have defined the behavior of this higher-order function to apply the arguments (2,3) on whatever function that is passed. Once we run the above program, the first output would be 5 and the second would be 6.

Method receivers

These are functions attached to struct types. Go does not have classes, unlike the other object-oriented languages. The closest types to classes are the struct types. We can define functions known as method receivers that are applicable to the specific struct type.

In addition to the usual function’s syntax, method receivers have the struct type on which they are applicable. Consider the following example below—

Here, Rectangle is a struct with two parameters — length, and breadth. To find the Area of the rectangle, one possible way is to create a function that takes in Rectangle struct as a parameter and calculates Area.

An object-oriented manner of doing the same is to create a method receiver on the Rectangle struct as written in the above code snippet. In this way, the client calling this method would not have the ability to manipulate the core fields inside the struct. This is the essence of encapsulation in object-oriented programming.

To calculate the Area of Rectangle, the client can invoke as follows —

Package oriented access

Many languages have a set of constraints on accessing entities from one module to another. For example in Java, there are predefined access specifiers — public, private, etc.. which are prefixed to a field or a function declaration. A public field is accessible from all modules in the application. A private field is accessible only inside the class in which it is defined.

In Go, access restriction is achieved through the Capitalisation of the identifier names. For example, functions or variable names that start with a capital letter are accessible everywhere across the application. Whereas the variable names that start with a non-capital letter are accessible only inside the package of definition.

A programming language is said to have first-class functions if it supports various features with functions such as passing functions are arguments, assigning functions to variables, returning a function from a function call. As we have seen from the above examples, Go supports first-class functions.

Even though Go supports some object-oriented principles, true power in Go comes with the mastery of functions.

Try out the features of functions here — https://play.golang.org/

--

--