Book Image

Go for DevOps

By : John Doak, David Justice
5 (1)
Book Image

Go for DevOps

5 (1)
By: John Doak, David Justice

Overview of this book

Go is the go-to language for DevOps libraries and services, and without it, achieving fast and safe automation is a challenge. With the help of Go for DevOps, you'll learn how to deliver services with ease and safety, becoming a better DevOps engineer in the process. Some of the key things this book will teach you are how to write Go software to automate configuration management, update remote machines, author custom automation in GitHub Actions, and interact with Kubernetes. As you advance through the chapters, you'll explore how to automate the cloud using software development kits (SDKs), extend HashiCorp's Terraform and Packer using Go, develop your own DevOps services with gRPC and REST, design system agents, and build robust workflow systems. By the end of this Go for DevOps book, you'll understand how to apply development principles to automate operations and provide operational insights using Go, which will allow you to react quickly to resolve system failures before your customers realize something has gone wrong.
Table of Contents (21 chapters)
1
Section 1: Getting Up and Running with Go
10
Section 2: Instrumenting, Observing, and Responding
14
Section 3: Cloud ready Go

Using conditionals

Go supports two types of conditionals, as follows:

  • if/else blocks
  • switch blocks

The standard if statement is similar to other languages with the addition of an optional init statement borrowed from the standard C-style for loop syntax.

switch statements provide a sometimes-cleaner alternative to if. So, let's jump into the if conditional.

if statements

if statements start with a familiar format that is recognizable in most languages:

if [expression that evaluates to boolean] {
     ...
} 

Here's a simple example:

if x > 2 { 
    fmt.Println("x is greater than 2") 
}

The statements within {} in if will execute if x has a value greater than 2.

Unlike most languages, Go has the ability to execute a statement within the if scope before the evaluation is made:

if [init statement];[statement that evaluates to boolean] {
     ...
}

Here is a simple example that is similar to the init statement in a for loop:

if err := someFunction(); err != nil { 
    fmt.Println(err) 
}

Here, we initialize a variable called err. It has a scope of the if block. If the err variable does not equal the nil value (a special value that indicates certain types are not set – more on this later), it will print the error.

else

If you need to execute something when the condition of an if statement is not met, you can use the else keyword:

if condition {
     function1()
}else {
     function2()
}

In this example, if the if condition is true, function1 will be executed. Otherwise, function2 occurs.

It should be noted that most uses of else can generally be eliminated for cleaner code. If your if condition results in returning from a function using the return keyword, you can eliminate else.

An example is as follows:

if v, err := someFunc(); err != nil {
     return err
}else{
     fmt.Println(v)
     return nil
}

This can be simplified to the following:

v, err := someFunc()
if err != nil {
     return err 
}
fmt.Println(v)
return nil

Sometimes, you want to only execute code if the if condition is not met and another condition is. Let's look at that next.

else if

An if block can also contain else if, providing multiple levels of execution. The first if or else if that is matched in order is executed.

Note that often Go developers choose the switch statement as a cleaner version of this type of conditional.

An example is as follows:

if x > 0 {
     fmt.Println("x is greater than 0")
} else if x < 0 {
     fmt.Println("x is less than 0")
} else{
     fmt.Println("x is equal to 0")
}

Now that we have seen the basics of this conditional, we need to talk about brace style.

if/else braces

It's time to introduce this rule: Opening braces for if/else must be on the line with the associated keyword. If there is another statement in the chain, it must start on the same line as the previous close brace.

With many languages, there are arguments about where to put the braces for loops/conditionals.

With Go, the authors decided to pre-empt those arguments with compiler checks. In Go, you can't do the following:

if x > 0 
{ // This must go up on the previous line
     fmt.Println("hello")
}
else { // This line must start on the previous line
     fmt.Println("world")
}

So, with the arguments on bracing style in Go settled, let's look at an alternative to if/else, the switch statement.

The switch statement

switch statements are more elegant if/else blocks that are very flexible in their use. They can be used for doing exact matching and multiple true/false evaluations.

Exact match switch

The following is an exact match switch:

switch [value] {
case [match]:
     [statement]
case [match], [match]:
     [statement]
default:
     [statement]
}

[value] is matched against each case statement. If it matches, the case statement executes. Unlike some languages, once a match occurs, no other case is considered. If no match occurs, the default statement executes. The default statement is optional.

This has a nicer syntax than if/else for handling cases where your value can be several values:

switch x {
case 3:
     fmt.Println("x is 3")
case 4, 5:  // executes if x is 4 or 5
     fmt.Println("x is 4 or 5")
default:
     fmt.Println("x is unknown")
}

switch can also have an init statement, similar to if:

switch x := someFunc(); x {
case 3:
     fmt.Println("x is 3")
} 

True/false evaluation switch

We can also eliminate [match] so that each case statement isn't an exact match, but a true/false evaluation (as with if statements):

switch {
case x > 0:
     fmt.Println("x is greater than 0")
case x < 0:
     fmt.Println("x is less than 0")
default:
     fmt.Println("x must be 0")
}

At the end of this section, you should be able to use Go's conditional statements to branch code execution in your program based on some criteria and handle cases where no statement was matched. As conditionals are one of the standard building blocks of software, we will use these in many of the remaining sections.