CategoryFor Loop

Concurrency and Goroutines in Go

In this post, we will be looking at goroutines in Go. Go is a language that was built with concurrency in mind. Given that almost all of the computers of the modern era employ the use of multiple cpu cores, this is a natural approach. Go makes use of a special feature called the Goroutine to handle concurrency. You can use these goroutines to call on lightweight threads to run a function. Before we take a look at examples, lets talk about concurrency for a moment.

Concurrency in Computing

Concurrency is the use of independent processes that work in an asynchronous order to complete a task. There are many examples of concurrency in the real world. We can look at how trains share tracks with one another, how in multiplayer games each player can make an action independent of one another, and how society in general works with each person making their own decisions. Naturally, many things use a model of concurrency.

Logically, it makes sense to apply this type of behavior to a computer program. When you download a file, listen to an audio stream, send a message over the web, print out a document, or even type in a text editor, you are making use of concurrency in programs. Some programming languages use different methods to handle concurrency and Go is certainly no exception with it’s goroutines. 

go-routines-gopher

Examples of Goroutines in Go

The simple definition of a goroutine, is a function that is capable of running concurrently with other functions. To invoke a goroutine, we simply place the word go in front of a function execution call. Let us look at a very simple example of this.

In this example we use a for-loop to iterate through ten values (0 to 9) inside of our function. Our main function has its own thread and in a way, the main function itself runs like a goroutine. We invoke a second goroutine with our function by typing go a(0). If we were to remove the goroutine and the Scanln function call, the function would run normally and then the program would end after execution. However, because the function is running on a separate thread then the main function, if we were to remove the Scanln call and leave the goroutine, the program will terminate before the end of the function. This happens because the main function doesn’t wait for the goroutine to end before moving on to execute the rest of the code.gopher_pipe

Because goroutines are very lightweight threads, we can literally call on thousands of them in a piece of code (the average 64 bit cpu can use 100,000 goroutines at once). Let us look at an example that uses many goroutines.

In this example, we are assigning ten threads (labeled 0 to 9) to our function by using our for loop. In our function, we are iterating through ten values again, however, each time we are now stopping and waiting for a random period of time which is between 0 and 250 milliseconds before the thread continues execution. In this way, we can see the way the threads are actually running parallel and concurrent to one another. You will notice that threads that were deployed before others may end execution well after the others have finished.

Conclusion

In this post we looked at how we can spawn threads and run functions concurrently in Go. The talked about goroutines and gave a general overview of concurrency. In our next few posts we will talk about how we can send data from one goroutine to the other using channels. 

How to Use Control Flow in Go

Control Flow in Go is an important concept. Control flow allows a program to execute in various different ways. You can force code to branch off, make code that loops back on itself, and match code to different instances. In this post, we will cover the some of the common forms of control flow in Go that we can use.

Using If/Else Statements in Go

if_else_go

The first most common style of control flow in Go is the if and if/else statement. If/else statements allow you to create branching code very easily. To do this, you need to use conditional statements and Boolean values. A Boolean value is a data type that can only be one of two values. In the case of Go, we have the true and the false keywords. Conditional statements in Go are statements that will resolve to Boolean values. Below are some examples of conditional statements in Go as well as some of the operators you can use to modify them.

We don’t have to use raw values in our conditionals, we can use variables as well. Here is the basic structure of an if/else statement in Go. Keep in mind that the else clause is not mandatory. Also, there is no ternary shorthand in Go like there is in JavaScript. 

In the code above, we have three different types of if/else statements. In an if/else statement, the code block under the if only runs if the conditional is true. If the conditional is not true and there isn’t a second conditional, then the else code block will run. In the first example above, the if statement checks to see if 9 is equal to 9 which it is. The first print function will be run and the print line in the else code block will be ignored. In the third example, the two conditionals are false, so the code in the if blocks is ignored. The last else block’s code will be run in this case.

Looping in Go

go_for_loopThe next major control flow operator is the for loop. The for loop allows us to loop through a block of code until the conditional is made false. This is a very good code structure for areas in your code that require multiple iterations. You can also use the break keyword to automatically “break” a for loop without making the conditional false. Let us look at some examples.

As you can see from these examples, for loops are very powerful constructs in Go. You can choose to loop over something as many times as you wish; though infinite loops tend to cause errors in normal programs. When we look at channels later in this tutorial we will look at other styles of for loops.

The Switch Operator in Go

switch_case
The last simple control flow structure in Go is the switch statement. A switch statement in Go is very similar to chaining if/else statements together. The major difference is that the syntax is not as redundant for larger pieces of code with many branches. In a switch statement, a code block will only run if its case is matched with the initial condition statement. Here is a simple example.

With the switch statement above, the value of i is being matched with the case number. In this case, because the variable i is equal to three, case 3 will execute and the rest will be ignored. The default case is a case that will run if none of the other cases are resolved to true. Here is a full program that showcases switch and default.

In this program, we assign a variable to the current day of the week using the time.Now().Weekday() function. We then check to see if that day is equal to Saturday or Sunday in our first case. If it is equal to Saturday or Sunday, then our first case will run. If it is not equal to Saturday or Sunday then our default case will execute. This example showcases the ability to combine cases as well as use other values for matching.

Conclusion

In this post, we looked at the control flow in Go. We used the if/else statement, the for loop, and the switch statement. We also looked at conditions and the different operators that we can use to make conditional statements in Go. We touched on Boolean values as well. In our next post, we will look at Arrays and Slices in Go.