DEV Community

Kervie Sazon
Kervie Sazon

Posted on

Go Learning Notes - Part 8: Concurrency & Goroutines

Today I explored Concurrency in Go using Goroutines and learned how Go can perform tasks in the background while the program continues executing. In my conference booking application, I implemented a goroutine to simulate sending a ticket confirmation email without blocking the main program.

Concurrency in Go

Concurrency allows a program to run multiple tasks independently. Go provides a simple way to achieve this using goroutines, which are lightweight threads managed by the Go runtime.

Instead of waiting for a task to finish, Go can run it in the background.

Goroutines with the go keyword

A goroutine is created by adding the go keyword before a function call.

In my program, I run the sendTicket function as a goroutine:

wg.Add(1)
go sendTicket(userTicket, fName, lName, email)
Enter fullscreen mode Exit fullscreen mode

This allows the program to continue running other code while the ticket is being "sent".

Simulating Work with time.Sleep

Inside the sendTicket function, I simulate a delay to represent sending an email.

time.Sleep(10 * time.second)
Enter fullscreen mode Exit fullscreen mode

This pauses the goroutines for 10 seconds.

Formatting Strings with fmt,Sprintf

I also used fmt.Sprintf to format a string without immediately printing it.

ticket := fmt.Sprintf("%v tickets for %v %v \n", userTickets, fName, lName)
Enter fullscreen mode Exit fullscreen mode

Unlike fmt.Printf, fmt.Sprintf returns the formatted string, which can then be stored in a variable or used later.

Synchronizing Goroutines with WaitGroup

When using goroutines, the program might finish before the goroutines complete.
To prevent this, Go provides the WaitGroup from the sync package.

var wg = sync.WaitGroup{}
Enter fullscreen mode Exit fullscreen mode

A WaitGroup helps the main program wait for all goroutines to finish before exiting.

Add()

Add() tells the WaitGroup how many goroutines to wait for.

wg.add(1)
Enter fullscreen mode Exit fullscreen mode

This means the program expects one goroutine to finish.

Done()

Inside the goroutine, Done() signals that the task is completed.

wg.Done()
Enter fullscreen mode Exit fullscreen mode

In my program, this is called at the of the sendTicket function.

Wait()

Wait() block the program until all goroutines have called Done()

wg.wait()
Enter fullscreen mode Exit fullscreen mode

This ensures the main program does not exit until the background task is finished.

Example: Sending Tickets Concurrently

My sendTicket function runs in the background and simulates sending a confirmation email.

func sendTicket(userTickets uint, fName string, lName string, email string) {
    time.Sleep(10 * time.Second)

    ticket := fmt.Sprintf("%v tickets for %v %v \n", userTickets, fName, lName)

    fmt.Println("############")
    fmt.Printf("Sending ticket: \n %v to email address %v \n", ticket, email)
    fmt.Println("############")

    wg.Done()
}
Enter fullscreen mode Exit fullscreen mode

This demonstrates how goroutines allow long-running tasks to execute without blocking the main application flow.

In summary, I learned how Go uses goroutines to run functions concurrently using the go keyword. I also learned how to simulate background tasks using time.Sleep and format strings using fmt.Sprintf. Another key concept I discovered was synchronizing goroutines using WaitGroup from the sync package. Using Add(), Done(), and Wait() ensures that goroutines complete their execution before the program exits.

Top comments (0)