Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Go for DevOps

You're reading from   Go for DevOps Learn how to use the Go language to automate servers, the cloud, Kubernetes, GitHub, Packer, and Terraform

Arrow left icon
Product type Paperback
Published in Jul 2022
Publisher Packt
ISBN-13 9781801818896
Length 634 pages
Edition 1st Edition
Languages
Tools
Concepts
Arrow right icon
Authors (2):
Arrow left icon
John Doak John Doak
Author Profile Icon John Doak
John Doak
David Justice David Justice
Author Profile Icon David Justice
David Justice
Arrow right icon
View More author details
Toc

Table of Contents (22) Chapters Close

Preface 1. Section 1: Getting Up and Running with Go
2. Chapter 1: Go Language Basics FREE CHAPTER 3. Chapter 2: Go Language Essentials 4. Chapter 3: Setting Up Your Environment 5. Chapter 4: Filesystem Interactions 6. Chapter 5: Using Common Data Formats 7. Chapter 6: Interacting with Remote Data Sources 8. Chapter 7: Writing Command-Line Tooling 9. Chapter 8: Automating Command-Line Tasks 10. Section 2: Instrumenting, Observing, and Responding
11. Chapter 9: Observability with OpenTelemetry 12. Chapter 10: Automating Workflows with GitHub Actions 13. Chapter 11: Using ChatOps to Increase Efficiency 14. Section 3: Cloud ready Go
15. Chapter 12: Creating Immutable Infrastructure Using Packer 16. Chapter 13: Infrastructure as Code with Terraform 17. Chapter 14: Deploying and Building Applications in Kubernetes 18. Chapter 15: Programming the Cloud 19. Chapter 16: Designing for Chaos 20. Index 21. Other Books You May Enjoy

Learning about functions

Functions in Go are what you'd expect from a modern programming language. There are only a few things that make Go functions different:

  • Multiple return values are supported
  • Variadic arguments
  • Named return values

The basic function signature is as follows:

func functionName([varName] [varType], ...) ([return value], [return value], ...){
}

Let's make a basic function that adds two numbers together and returns the result:

func add(x int, y int) int {
     return x + y
}

As you can see, this takes in two integers, x and y, adds them together, and returns the result (which is an integer). Let's show how we can call this function and print its output:

result := add(2, 2)
fmt.Println(result)

We can simplify this function signature by declaring both x and y types with a single int keyword:

func add(x, y int) int {
     return x + y
}

This is equivalent to the previous one.

Returning multiple values and named results

In Go, we can return multiple values. For example, consider a function that divides two integers and returns two variables, the result and the remainder, as follows:

func divide(num, div int) (res, rem int) {
	result = num / div
	remainder = num % div
	return res, rem
}

This code demonstrates a few new features in our function:

  • Argument num is the number to be divided
  • Argument div is the number to divide by
  • Return value res is the result of the division
  • Return value rem is the remainder of the division

First is named returns (res and rem). These variables are automatically created and ready for use inside the function.

Notice I use = and not := when doing assignments to those variables. This is because the variable already exists, and we want to assign a value (=). := means create and assign. You can only create a new variable that doesn't exist. You will also notice that now the return type is in parenthesis. You will need to use parenthesis if you use more than one return value or named returns (or in this case, both).

Calling this function is just as simple as calling add() before, as shown here:

result, remainder := divide(3, 2)
fmt.Printf("Result: %d, Remainder %d", result, remainder)

Strickly speaking, you don't have to use return to return the values. However, doing so will prevent some ugly bugs that you will eventually encounter.

Next, we will look at how we can have a variable number of arguments as function input that allows us to create functions such as fmt.Println(), which you have been using in this chapter.

Variadic arguments

A variadic argument is when you want to provide 0 to infinite arguments. A good example would be calculating a sum of integers. Without variadic arguments, you might use a slice (a growable array type, which we will talk about later), as follows:

func sum(numbers []int) int {
     sum := 0
     for _, n := range numbers {
          sum += n
     }
     return sum
}

While this is fine, using it is cumbersome:

args := []int{1,2,3,4,5}
fmt.Println(sum(args))

We can accomplish this same thing by using the variadic (...) notation:

func sum(numbers ...int) int {
     // Same code
}

numbers is still []int, but has a different calling convention that is more elegant:

fmt.Println(sum(1,2,3,4,5))

Note

You can use variadic arguments with other arguments, but it must be the last argument in the function.

Anonymous functions

Go has a concept of anonymous functions, which means a function without a name (also called a function closure).

This can be useful to take advantage of special statements that honor function boundaries, such as defer, or in goroutines. We will show how to take advantage of these for goroutines later, but for now let's show how to execute an anonymous function. This is a contrived example that is only useful in teaching the concept:

func main() {
     result := func(word1, word2 string) string {
          return word1 + " " + word2
     }("hello", "world")
     fmt.Println(result)
}

This code does the following:

  • Defines a single-use function (func(word1, word2 string) string)
  • Executes the function with the hello and world arguments
  • Assigns the string return value to the result variable
  • Prints result

Now that we have arrived at the end of this section, we have learned about how Go functions are declared, the use of multiple return values, variadic arguments for simplified function calling, and anonymous functions. Multiple return values will be important in future chapters where we deal with errors, and anonymous functions are key components of our future defer statements and for use with concurrency.

In the next section, we will explore public and private types.

You have been reading a chapter from
Go for DevOps
Published in: Jul 2022
Publisher: Packt
ISBN-13: 9781801818896
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime