Select و WaitGroup
select برای چندگانهسازی Channel، WaitGroup برای صبر و Mutex برای قفل.
select — منتظر چند Channel
select مثل switch اما برای Channel ها — منتظر میماند تا یکی آماده شود:
select {
case msg := <-ch1:
fmt.Println("از کانال ۱:", msg)
case msg := <-ch2:
fmt.Println("از کانال ۲:", msg)
}
مثال: مسابقه دو کانال
ch1 := make(chan string)
ch2 := make(chan string)
go func() { time.Sleep(time.Second); ch1 <- "اولی" }()
go func() { time.Sleep(2 * time.Second); ch2 <- "دومی" }()
for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println("دریافت:", msg1)
case msg2 := <-ch2:
fmt.Println("دریافت:", msg2)
}
}
select با timeout
select {
case msg := <-ch:
fmt.Println("دریافت شد:", msg)
case <-time.After(2 * time.Second):
fmt.Println("مهلت تمام شد!") ← timeout
}
select با default (غیربلاک)
select {
case msg := <-ch:
fmt.Println(msg)
default:
fmt.Println("دادهای موجود نیست") ← بدون صبر
}
sync.WaitGroup — صبر برای گروهی از کارها
var wg sync.WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1) ← شمارنده +۱
go func(n int) {
defer wg.Done() ← شمارنده -۱
fmt.Println("کار", n)
}(i)
}
wg.Wait() ← صبر تا صفر شود
fmt.Println("همه کارها تمام شد")
sync.Mutex — قفل متقابل
وقتی چند Goroutine به متغیر مشترک دسترسی دارند:
var (
counter int
mu sync.Mutex
)
func increment() {
mu.Lock() ← قفل
counter++
mu.Unlock() ← باز کردن
}
بدون Mutex، شرط مسابقه (Race Condition) رخ میدهد — نتیجهها نادرست و غیرقابل پیشبینی میشوند!
مثال کامل: شمارنده امن
func main() {
var (
counter int
mu sync.Mutex
wg sync.WaitGroup
)
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
mu.Lock()
counter++
mu.Unlock()
}()
}
wg.Wait()
fmt.Println(counter) ← همیشه 100 ✓
}
جمعبندی ابزارهای همزمانی
| ابزار | کاربرد |
|---|---|
go | اجرای همزمان |
channel | ارتباط و انتقال داده |
select | چندگانهسازی کانالها |
sync.WaitGroup | صبر برای اتمام گروه |
sync.Mutex | قفل متغیر مشترک |
این مبحث بخشی از دوره آموزش کامل گو است.