Goroutine Basics
What is a Goroutine?
In Go programming, a goroutine is a lightweight thread managed by the Go runtime. Unlike traditional threads, goroutines are extremely cheap to create and can be spawned in thousands without significant performance overhead. They are the fundamental unit of concurrency in Go.
Creating Goroutines
Goroutines are created using the go
keyword followed by a function call. Here's a simple example:
package main
import (
"fmt"
"time"
)
func printMessage(message string) {
fmt.Println(message)
}
func main() {
// Create a goroutine
go printMessage("Hello from goroutine!")
// Main goroutine continues
fmt.Println("Main goroutine")
// Add a small delay to allow goroutine to execute
time.Sleep(time.Second)
}
Goroutine Characteristics
Characteristic |
Description |
Lightweight |
Minimal memory overhead |
Scalable |
Can create thousands of goroutines |
Managed by Go Runtime |
Scheduled and managed automatically |
Communication |
Use channels for safe communication |
Concurrency vs Parallelism
graph TD
A[Concurrency] --> B[Multiple tasks in progress]
A --> C[Not necessarily simultaneous]
D[Parallelism] --> E[Multiple tasks executed simultaneously]
D --> F[Requires multiple CPU cores]
Goroutine Scheduling
Go uses a sophisticated scheduling model called the M:N scheduler, where:
- M represents OS threads
- N represents goroutines
- The runtime maps goroutines to threads efficiently
Best Practices
- Keep goroutines short and focused
- Use channels for communication
- Avoid sharing memory directly
- Be mindful of goroutine lifecycle
Example: Concurrent Web Scraper
func fetchURL(url string, ch chan string) {
resp, err := http.Get(url)
if err != nil {
ch <- fmt.Sprintf("Error fetching %s: %v", url, err)
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
ch <- fmt.Sprintf("Content from %s: %d bytes", url, len(body))
}
func main() {
urls := []string{
"https://example.com",
"https://labex.io",
"https://golang.org",
}
ch := make(chan string, len(urls))
for _, url := range urls {
go fetchURL(url, ch)
}
for i := 0; i < len(urls); i++ {
fmt.Println(<-ch)
}
}
When to Use Goroutines
- I/O-bound operations
- Parallel processing
- Background tasks
- Handling multiple connections
By understanding these basics, developers can leverage the power of goroutines to create efficient, concurrent Go applications.