Go > Concurrency > Goroutines > Creating goroutines
Creating Goroutines in Go
This example demonstrates how to create and run goroutines in Go, showcasing the basic syntax and functionality.
Basic Goroutine Creation
This code demonstrates the simplest way to start a goroutine. The `go` keyword before a function call launches that function in a new, concurrently executing goroutine. The `greet` function simply prints a greeting. The `time.Sleep` call is crucial here, as it allows time for the goroutines to execute before the `main` function exits. Without it, the program might terminate before the goroutines have a chance to run, leading to no output from the `greet` functions.
package main
import (
"fmt"
"time"
)
func greet(name string) {
fmt.Printf("Hello, %s!\n", name)
}
func main() {
go greet("Alice")
go greet("Bob")
// Wait for goroutines to finish. Without this, main might exit before goroutines run.
time.Sleep(time.Second)
fmt.Println("Main function finished.")
}
Understanding the Code
The go
keyword is the heart of goroutine creation. When you prepend a function call with go
, the Go runtime spawns a new lightweight thread of execution and runs the function in that thread. Importantly, the main function doesn't wait for the goroutine to finish before proceeding to the next line of code. This allows for concurrent execution.
Concepts Behind the Snippet
Real-Life Use Case
Imagine a web server that needs to handle multiple incoming requests concurrently. Each request can be handled by a separate goroutine, allowing the server to remain responsive even when handling many requests simultaneously. Another use case is in data processing pipelines where different stages of the pipeline can run concurrently, processing data in parallel.
Best Practices
context
package to manage the lifecycle of goroutines, allowing you to cancel them gracefully when needed.
Interview Tip
Be prepared to explain the difference between concurrency and parallelism. Also, be ready to discuss common concurrency pitfalls like race conditions and how to avoid them using synchronization primitives like mutexes and channels.
When to Use Them
Use goroutines when you have tasks that can be executed independently and concurrently, such as handling multiple network requests, processing data in parallel, or performing background tasks. They are especially useful in I/O-bound applications where waiting for I/O operations can be overlapped by other tasks.
Memory Footprint
Goroutines are designed to be lightweight, typically starting with a small stack size (e.g., 2KB), which can grow dynamically as needed. This allows you to create and manage a large number of goroutines without excessive memory consumption.
Alternatives
While goroutines are Go's primary mechanism for concurrency, alternatives include using worker pools with channels or using external libraries that provide higher-level concurrency abstractions. However, for most common concurrency scenarios, goroutines are the preferred and most efficient approach.
Pros
go
keyword makes it easy to launch concurrent tasks.
Cons
FAQ
-
What happens if I don't wait for the goroutines to finish?
If the main function exits before the goroutines finish, the program will terminate, and any unfinished work in the goroutines will be lost. That's why thetime.Sleep
call (or more robust synchronization mechanisms) is essential. -
How do I pass data to a goroutine?
You can pass data to a goroutine by including arguments in the function call that is launched with thego
keyword. The arguments are passed by value, so the goroutine receives a copy of the data. -
How do goroutines communicate with each other?
Goroutines typically communicate with each other using channels, which are a built-in type in Go that allows for safe and efficient data transfer between concurrent processes. Mutexes can also be used for protecting shared resources.