🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

اذهب إلى دليل التزامن 2026: الإجراءات والقنوات وأنماط الإنتاج

⏱️4 min read  ·  821 words

يعد نموذج التزامن الخاص بـ Go — goroutines والقنوات — هو أبسط وأقوى نظام تزامن في أي لغة سائدة. في عام 2026، يعمل الإصدار 1.23 من Go مع مكررات النطاق فوق الوظيفة والتسجيل المنظم للسجل على جعل كود Go المتزامن أكثر نظافة من أي وقت مضى. يغطي هذا الدليل كل شيء بدءًا من الإجراءات الأساسية وحتى أنماط الإنتاج.

Goroutines – خيوط خفيفة الوزن

package main

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

func main() {
	// goroutine = lightweight thread (starts with 2KB stack, not 1MB like OS threads)
	go sayHello("World")     // fire and forget

	// Wait for goroutine using WaitGroup
	var wg sync.WaitGroup

	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func(id int) {
			defer wg.Done()
			fmt.Printf("Worker %d done
", id)
			time.Sleep(time.Duration(id) * time.Millisecond)
		}(i)
	}

	wg.Wait() // block until all goroutines finish
	fmt.Println("All workers done")
}

func sayHello(name string) {
	time.Sleep(10 * time.Millisecond)
	fmt.Printf("Hello, %s!
", name)
}

القنوات – التواصل بين Goroutines

package main

import "fmt"

func main() {
	// Unbuffered channel — sender blocks until receiver ready
	ch := make(chan int)

	go func() {
		ch <- 42  // send
	}()

	value := <-ch  // receive
	fmt.Println(value)  // 42

	// Buffered channel — sender blocks only when buffer full
	buffered := make(chan string, 5)
	buffered <- "hello"
	buffered <- "world"
	// Doesn't block because buffer has space
	close(buffered)

	// Range over closed channel
	for msg := range buffered {
		fmt.Println(msg)
	}

	// Directional channels in function signatures
	produce := func(ch chan<- int) {  // send-only
		for i := 0; i < 5; i++ {
			ch <- i
		}
		close(ch)
	}

	consume := func(ch <-chan int) {  // receive-only
		for n := range ch {
			fmt.Println("received:", n)
		}
	}

	dataCh := make(chan int, 10)
	go produce(dataCh)
	consume(dataCh)
}

حدد — تعدد القنوات

package main

import (
	"context"
	"fmt"
	"time"
)

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

	go func() {
		time.Sleep(100 * time.Millisecond)
		ch1 <- "from ch1"
	}()

	go func() {
		time.Sleep(200 * time.Millisecond)
		ch2 <- "from ch2"
	}()

	// Select picks whichever channel is ready first
	for i := 0; i < 2; i++ {
		select {
		case msg1 := <-ch1:
			fmt.Println(msg1)
		case msg2 := <-ch2:
			fmt.Println(msg2)
		}
	}

	// With timeout
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	select {
	case result := <-fetchData():
		fmt.Println(result)
	case <-ctx.Done():
		fmt.Println("timeout:", ctx.Err())
	}

	// Non-blocking send with default
	ch := make(chan int, 1)
	select {
	case ch <- 42:
		fmt.Println("sent")
	default:
		fmt.Println("channel full, skipped")
	}
}

نمط تجمع العمال

package main

import (
	"fmt"
	"sync"
)

type Job struct {
	ID   int
	Data string
}

type Result struct {
	JobID  int
	Output string
	Err    error
}

func workerPool(numWorkers int, jobs <-chan Job, results chan<- Result) {
	var wg sync.WaitGroup
	for i := 0; i < numWorkers; i++ {
		wg.Add(1)
		go func(workerID int) {
			defer wg.Done()
			for job := range jobs {
				output, err := processJob(job)
				results <- Result{JobID: job.ID, Output: output, Err: err}
			}
		}(i)
	}

	// Close results channel when all workers done
	go func() {
		wg.Wait()
		close(results)
	}()
}

func processJob(job Job) (string, error) {
	return fmt.Sprintf("processed: %s", job.Data), nil
}

func main() {
	jobs := make(chan Job, 100)
	results := make(chan Result, 100)

	// Start 5 workers
	go workerPool(5, jobs, results)

	// Send 20 jobs
	go func() {
		for i := 0; i < 20; i++ {
			jobs <- Job{ID: i, Data: fmt.Sprintf("item-%d", i)}
		}
		close(jobs)
	}()

	// Collect results
	for result := range results {
		if result.Err != nil {
			fmt.Printf("Job %d failed: %v
", result.JobID, result.Err)
			continue
		}
		fmt.Printf("Job %d: %s
", result.JobID, result.Output)
	}
}

السياق – الإلغاء والمواعيد النهائية

package main

import (
	"context"
	"fmt"
	"time"
)

func fetchWithContext(ctx context.Context, url string) (string, error) {
	// Check if context already cancelled
	select {
	case <-ctx.Done():
		return "", ctx.Err()
	default:
	}

	// Simulate slow operation
	done := make(chan string, 1)
	go func() {
		time.Sleep(500 * time.Millisecond)
		done <- "data from " + url
	}()

	select {
	case data := <-done:
		return data, nil
	case <-ctx.Done():
		return "", ctx.Err()
	}
}

func main() {
	// Context with deadline
	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancel()

	data, err := fetchWithContext(ctx, "https://api.example.com/data")
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println(data)

	// Pass context to database queries (Go standard pattern)
	// db.QueryContext(ctx, "SELECT ...")
	// http.NewRequestWithContext(ctx, "GET", url, nil)
}

حزمة المزامنة – كائنات المزامنة ومرة ​​واحدة

package main

import (
	"fmt"
	"sync"
	"sync/atomic"
)

// Mutex for shared state
type SafeCounter struct {
	mu    sync.RWMutex
	count map[string]int
}

func (c *SafeCounter) Increment(key string) {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.count[key]++
}

func (c *SafeCounter) Get(key string) int {
	c.mu.RLock()  // multiple readers allowed simultaneously
	defer c.mu.RUnlock()
	return c.count[key]
}

// sync.Once — run initialization exactly once
var (
	dbOnce     sync.Once
	dbInstance *Database
)

func GetDB() *Database {
	dbOnce.Do(func() {
		dbInstance = &Database{} // initialized exactly once, even concurrent calls
	})
	return dbInstance
}

// Atomic operations — lockless for simple counters
var requestCount int64

func handleRequest() {
	atomic.AddInt64(&requestCount, 1)
	// Process request...
}

func getRequestCount() int64 {
	return atomic.LoadInt64(&requestCount)
}

errgroup — الأخطاء المتزامنة

package main

import (
	"context"
	"fmt"

	"golang.org/x/sync/errgroup"
)

func main() {
	ctx := context.Background()

	// Run goroutines, collect first error
	g, ctx := errgroup.WithContext(ctx)

	var user, posts, stats interface{}

	g.Go(func() error {
		var err error
		user, err = fetchUser(ctx, 1)
		return err
	})

	g.Go(func() error {
		var err error
		posts, err = fetchPosts(ctx, 1)
		return err
	})

	g.Go(func() error {
		var err error
		stats, err = fetchStats(ctx, 1)
		return err
	})

	// Wait for all goroutines
	if err := g.Wait(); err != nil {
		fmt.Println("Error:", err)
		return
	}

	fmt.Println(user, posts, stats)
}

يعد التزامن في عام 2026 أمرًا أنيقًا وقويًا عندما تتبع الشعار: “شارك الذاكرة من خلال التواصل، ولا تتواصل من خلال مشاركة الذاكرة”. استخدم goroutines بحرية (تكلفة كل منها حوالي 2 كيلو بايت)، والتنسيق مع القنوات وWaitGroups، والتعامل مع إلغاء السياق في جميع العمليات طويلة الأمد، وتجنب الحالة القابلة للتغيير المشتركة (تفضيل القنوات أو العمليات الذرية).

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা