Golang Concurrency - Go-routines

If you're a programmer, you will find many instances where its better to do multiple things concurrently, rather than one after the other. Of course, this comes with the cost of added complexity and hidden bugs just waiting to show up when you least expect them.

Many programming languages have different way of dealing with concurrency, but I find that the method that Go uses is one of the simplest and most elegant ones to learn.

In this post, we will learn the concept of a Go-routine, and how we can use it to execute multiple tasks concurrently.

The task

Let's begin with an example: our program is going to simulate a kitchen, where we need to chop some vegetables in order to make a salad. As we know, chopping a vegetable takes some amount of time to complete, which we will represent as a delay:

// Each vegetable has a name and a chopped status
type vegetable struct {
	name    string
	chopped bool
}

// Each vegetable also has a chop method, inside which
// we add a delay of 50 milliseconds, before setting the
// vegetables chopped status to true
func (v *vegetable) chop() {
	time.Sleep(50 * time.Millisecond)
	v.chopped = true
}

In our non-concurrent program, we just chop our vegetables one by one, and let the user know once we're done:

func main() {
	// initialize our vegetables
	tomato := &vegetable{name: "tomato"}
	cucumber := &vegetable{name: "cucumber"}

	// Chop the vegetables
	tomato.chop()
	cucumber.chop()

	// Print the status of the vegetables
	fmt.Println("Chopped vegetables:")
	fmt.Println("tomato:", tomato.chopped)
	fmt.Println("cucumber:", cucumber.chopped)
}

We don't actually need to chop the tomato and cucumber one after the other. We can run the tomato's chop method in a separate go routine by using the go keyword:

func main() {
	tomato := &vegetable{name: "tomato"}
	cucumber := &vegetable{name: "cucumber"}

	// Call tomato's chop method as a goroutine
	go tomato.chop()
	// Cucumbers chop method blocks the main function
	cucumber.chop()

	fmt.Println("Chopped vegetables:")
	fmt.Println("tomato:", tomato.chopped)
	fmt.Println("cucumber:", cucumber.chopped)
}

We can illustrate the tomato's chop method executing in a different go routine:

📖 Read next: Variables


Liked this article? Share it on: