Post

Concurrency in Go

Concurrency in Go

Concurrency is a fundamental concept in Go, allowing developers to write programs that can perform multiple tasks simultaneously. Go’s concurrency model is built around goroutines and channels, making it easy to manage concurrent operations without the complexity of traditional threading models.

1. Goroutines

Goroutines are lightweight threads managed by the Go runtime. They are created using the go keyword followed by a function call. When a goroutine is launched, it runs concurrently with the rest of the program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
import (
  "fmt"
  "time"
)

func sayHello() {
  fmt.Println("Hello from Goroutine!")
}

func main() {
  go sayHello() // Launching a goroutine
  time.Sleep(1 * time.Second) // Wait for the goroutine to finish
  fmt.Println("Main function finished.")
}

In this example, the sayHello function is executed concurrently with the main function. The time.Sleep function is used to give the goroutine enough time to complete before the program exits.

2. Channels

Channels are a powerful feature in Go that allows goroutines to communicate with each other. They provide a way to send and receive values between goroutines, enabling synchronization and coordination.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import (
  "fmt"
)

func worker(ch chan string) {
  ch <- "Hello from Worker!" // Sending a message to the channel
}

func main() {
  ch := make(chan string) // Creating a channel
  go worker(ch) // Launching a goroutine
  message := <-ch // Receiving a message from the channel
  fmt.Println(message)
}

In this example, the worker function sends a message to the channel, and the main function receives it. This allows for safe communication between goroutines without the need for explicit locks or mutexes.

3. Select Statement

The select statement is used to wait on multiple channel operations. It allows a goroutine to wait for multiple communication operations, making it easier to handle multiple channels concurrently.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main
import (
  "fmt"
  "time"
)

func worker(ch chan string) {
  time.Sleep(2 * time.Second)
  ch <- "Worker finished!"
}

func main() {
  ch1 := make(chan string)
  ch2 := make(chan string)

  go worker(ch1)
  go worker(ch2)

  select {
  case msg1 := <-ch1:
    fmt.Println(msg1)
  case msg2 := <-ch2:
    fmt.Println(msg2)
  }
}

In this example, the select statement waits for either ch1 or ch2 to receive a message. The first channel that sends a message will be processed, allowing for efficient handling of multiple concurrent operations.

4. WaitGroup

A WaitGroup is used to wait for a collection of goroutines to finish executing. It provides a way to synchronize the completion of multiple goroutines.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import (
  "fmt"
  "sync"
  "time"
)

func worker(wg *sync.WaitGroup) {
  defer wg.Done() // Decrement the counter when the goroutine completes
  time.Sleep(2 * time.Second)
  fmt.Println("Worker finished!")
}

func main() {
  var wg sync.WaitGroup
  wg.Add(2) // Set the number of goroutines to wait for

  go worker(&wg)
  go worker(&wg)

  wg.Wait() // Wait for all goroutines to finish
  fmt.Println("All workers finished!")
}

In this example, the WaitGroup is used to wait for two goroutines to finish. The wg.Add(2) method sets the number of goroutines to wait for, and wg.Done() is called when each goroutine completes. The wg.Wait() method blocks until all goroutines have finished executing.

Conclusion

Concurrency in Go is a powerful feature that allows developers to write efficient and scalable programs. By using goroutines, channels, and synchronization primitives like WaitGroup, you can easily manage concurrent operations without the complexity of traditional threading models. Understanding these concepts is essential for building robust and high-performance applications in Go.

Further Reading

This post is licensed under CC BY 4.0 by the author.