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

Go Concurrency Guide 2026: Goroutines, Chanels এবং Production Patterns

⏱️4 min read  ·  820 words

Go-এর কনকারেন্সি মডেল — গরউটিন এবং চ্যানেল — যে কোনও মূলধারার ভাষায় সবচেয়ে সহজ এবং সবচেয়ে শক্তিশালী কনকারেন্সি সিস্টেম। 2026 সালে, রেঞ্জ-ওভার-ফাংশন ইটারেটর এবং স্লগ স্ট্রাকচার্ড লগিং সহ Go 1.23 সমসাময়িক Go কোডকে আগের চেয়ে আরও পরিষ্কার করে তোলে। এই নির্দেশিকা মৌলিক গোরুটিন থেকে উত্পাদন নিদর্শন সবকিছু কভার করে.

গোরুটিনস — লাইটওয়েট থ্রেড

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)
}

চ্যানেলগুলি — গোরুটিনের মধ্যে যোগাযোগ

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)
}

সিঙ্ক প্যাকেজ — Mutexes এবং একবার

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 সালে Go concurrency মার্জিত এবং শক্তিশালী হয় যখন আপনি এই মন্ত্রটি অনুসরণ করেন: “যোগাযোগ করে মেমরি শেয়ার করুন, মেমরি শেয়ার করে যোগাযোগ করবেন না।” গরউটিনগুলি অবাধে ব্যবহার করুন (এগুলির প্রতিটির দাম ~2KB), চ্যানেল এবং ওয়েটগ্রুপগুলির সাথে সমন্বয় করুন, সমস্ত দীর্ঘ-চলমান ক্রিয়াকলাপে প্রসঙ্গ বাতিলকরণ পরিচালনা করুন এবং ভাগ করা পরিবর্তনযোগ্য অবস্থা এড়িয়ে চলুন (চ্যানেল বা পারমাণবিক অপারেশন পছন্দ করুন)।

✍️ Leave a Comment

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

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