Goroutines and Channels
Concurrent programming with goroutines and channel communication
#goroutines #channels #concurrency #async
Goroutines and Channels
Go's approach to concurrent programming using lightweight goroutines and channels.
Basic Goroutine
package main
import (
"fmt"
"time"
)
func sayHello() {
fmt.Println("Hello from goroutine!")
}
func main() {
go sayHello() // Run in background
time.Sleep(time.Second) // Wait for goroutine
fmt.Println("Main function")
}
Anonymous Goroutine
func main() {
go func() {
fmt.Println("Anonymous goroutine")
}()
time.Sleep(time.Second)
}
Basic Channel
func main() {
messages := make(chan string)
go func() {
messages <- "Hello" // Send to channel
}()
msg := <-messages // Receive from channel
fmt.Println(msg)
}
Buffered Channels
func main() {
messages := make(chan string, 2) // Buffer of 2
messages <- "Hello"
messages <- "World"
// Would block: messages <- "!" // Buffer full
fmt.Println(<-messages) // Hello
fmt.Println(<-messages) // World
}
Channel Synchronization
func worker(done chan bool) {
fmt.Println("Working...")
time.Sleep(time.Second)
done <- true // Signal completion
}
func main() {
done := make(chan bool)
go worker(done)
<-done // Wait for completion
fmt.Println("Done!")
}
Channel Direction
// Send-only channel
func sender(ch chan<- string) {
ch <- "message"
}
// Receive-only channel
func receiver(ch <-chan string) {
msg := <-ch
fmt.Println(msg)
}
func main() {
ch := make(chan string)
go sender(ch)
receiver(ch)
}
Range Over Channel
func main() {
numbers := make(chan int)
go func() {
for i := 0; i < 5; i++ {
numbers <- i
}
close(numbers) // Close when done
}()
for num := range numbers {
fmt.Println(num) // 0, 1, 2, 3, 4
}
}
Select Statement
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(time.Second)
ch1 <- "one"
}()
go func() {
time.Sleep(2 * time.Second)
ch2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println("Received", msg1)
case msg2 := <-ch2:
fmt.Println("Received", msg2)
}
}
}
Worker Pool Pattern
func worker(id int, jobs <-chan int, results chan<- int) {
for job := range jobs {
fmt.Printf("Worker %d processing job %d\n", id, job)
time.Sleep(time.Second)
results <- job * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
// Start 3 workers
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// Send 5 jobs
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
// Collect results
for a := 1; a <= 5; a++ {
<-results
}
}
Timeout with Select
func main() {
ch := make(chan string)
go func() {
time.Sleep(2 * time.Second)
ch <- "result"
}()
select {
case res := <-ch:
fmt.Println(res)
case <-time.After(1 * time.Second):
fmt.Println("Timeout!")
}
}
Non-Blocking Channel Operations
func main() {
messages := make(chan string)
select {
case msg := <-messages:
fmt.Println("Received:", msg)
default:
fmt.Println("No message available")
}
}
WaitGroup for Synchronization
import "sync"
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1)
go worker(i, &wg)
}
wg.Wait() // Wait for all goroutines
fmt.Println("All workers done")
}
Discover another handy tool from EditPDF.pro