Skip to Content
Go Realm v1 is released 🎉
Go Routines🧭 Day 2

🍀 Channels কী?

Goroutine গুলো স্বাধীনভাবে চলে, তাই তাদের মধ্যে তথ্য আদান-প্রদান বা সিঙ্ক্রোনাইজেশনের (Sync) জন্য দরকার হয় একটি safe communication mechanism

Channel হচ্ছে সেই নিরাপদ পাইপলাইন, যেখানে:

  • এক Goroutine তথ্য পাঠায় (chan <-)
  • অন্য Goroutine তথ্য গ্রহণ করে (<- chan)

channel দিয়ে গোরুটিনগুলো একে অপরের সাথে “কথা বলে”।

Go বলে:

“Don’t communicate by sharing memory; share memory by communicating.”

মানে: একসাথে memory-তে read/write না করে, ডেটা channel দিয়ে পাস করো — তাতে লক (mutex) না লাগলেও concurrency safe থাকে।

কেন চ্যানেল দরকার?

ধরো, দুইটা goroutine একই variable-এ write করছে:

x = x + 1

যদি দুজন একসাথে লেখে, তখন value corrupt হতে পারে (race condition)।

এটি এভাবে fix করা যায়:

  • Mutex lock
  • Atomic operations
  • Shared memory coordination

কিন্তু Go বলে:

“Don’t communicate by sharing memory; share memory by communicating.”

মানে: Variable share করো না। Data পাঠাও। তাহলেই code naturally safe থাকে।

এজন্যই channel ব্যবহার করা হয়।



1) Channel তৈরি

ch := make(chan int) // unbuffered ch2 := make(chan string, 3) // buffered, capacity 3

এখানে ch শুধু int send/receive করতে পারবে।


Channel internal model:

Sender → [ Channel ] → Receiver

Channel নিজেই data queue ধরে রাখে (buffer থাকলে queue বড় হয়)।


2) Sending ও Receiving বিস্তারিত

Send:

ch <- x

Receive:

v := <-ch

Unbuffered channel-এ:

Sender send করতে গিয়ে অপেক্ষা করে ⏳ Receiver receive করতে গিয়ে অপেক্ষা করে ⏳

যেখানে দুজন মিলবে, সেখানেই data transfer হবে এবং দুজনই release হবে।

Unbuffered Timing Diagram

Time → Sender: ----[ Send(n) ]------ wait ----> paired ----> done Receiver: -------- wait --------[ Receive ]------------> done

অর্থ:

Sender ও Receiver একই সময় data exchange করে। এটা handshake-like synchronization।

2) Send & Receive (Unbuffered Channel)

package main import "fmt" func main() { ch := make(chan int) go func() { ch <- 10 // send }() value := <-ch // receive fmt.Println(value) }

এখানে কী হচ্ছে?

  • Sender ch <- 10 পর্যন্ত এসে receiver না আসা পর্যন্ত অপেক্ষা করবে
  • Receiver <-ch পর্যন্ত এসে sender না পাঠানো পর্যন্ত অপেক্ষা করবে

➡️ Unbuffered channel sender এবং receiver দুইজনকেই অপেক্ষায় রাখে = synchronization


3) Buffered Channel

ch := make(chan int, 2)

এখানে channel-এর capacity = 2।

Buffer = Queue = Channel-এর ভেতরে memory।

package main import "fmt" func main() { ch := make(chan int, 2) ch <- 1 ch <- 2 // OK, buffer full // ch <- 3 // এখানে deadlock, কারণ buffer পূর্ণ → receiver নেই fmt.Println(<-ch) fmt.Println(<-ch) }

Buffered Timing Diagram

Initial: [ empty ] Send → [ 1 ] Send → [ 1, 2 ] (full now) Next Send → block! (receiver needed here)

Receiver:

Receive → pops 1 → [ 2 ] Receive → pops 2 → [ empty ]

পার্থক্য ( Timing ধারণা )

চ্যানেলআচরণকবে send block হয়?কবে receive block হয়?
UnbufferedSend ও Receive দুজনই একে অপরের জন্য অপেক্ষা করেযতক্ষণ receiver ready না হয়যতক্ষণ sender কিছু না পাঠায়
Bufferedযতক্ষণ buffer-এ জায়গা আছে, sender অপেক্ষা করে নাBuffer পূর্ণ হলেBuffer খালি হলে

4) Channel বন্ধ করা (close)

close(ch)

Close করা মানে:

  • আর send করা যাবে না (send করলে panic)
  • কিন্তু receive করা যাবে (zero-value + ok flag)

বন্ধ করা কেন দরকার?

♦️ বোঝাতে যে আর ডেটা আসবে না

Receive with ok flag:

v, ok := <-ch if !ok { fmt.Println("Channel closed") }

Channel-এর ওপর loop করা (for-range):

for v := range ch { fmt.Println(v) }

range channel close হওয়া পর্যন্ত চলবে।


Channel-এর আকার দেখা

len(ch) // buffer এ কয়টা item আছে cap(ch) // buffer capacity

উপকারী debugging এ।

সাধারণ ভুলগুলো (সবচেয়ে গুরুত্বপূর্ণ অংশ)

ভুলফলাফলকেন
Receive আছে কিন্তু Send নেইDeadlockকেউ data পাঠাচ্ছে না
Send আছে কিন্তু Receive নেইDeadlockchannel overflow (unbuffered)
Buffered full, but no receiverDeadlockbuffer পূর্ণ হয়ে গেছে
Close করার পর sendPanicবন্ধ channel-এ লেখা যায় না
Close না করে range করলেInfinite waitকখনো close ধরবে না

✅ অনুশীলন ১: Unbuffered Channel Synchronization Proof

package main import ( "fmt" "time" ) func main() { ch := make(chan string) go func() { fmt.Println("Sender: preparing") time.Sleep(2 * time.Second) fmt.Println("Sender: sending") ch <- "Hello" fmt.Println("Sender: done send") }() time.Sleep(1 * time.Second) fmt.Println("Receiver: waiting...") msg := <-ch fmt.Println("Receiver got:", msg) }

Output reasoning:

Sender: preparing Receiver: waiting... Sender: sending Receiver got: Hello Sender: done send

দেখো send এবং receive handshake এর মত synchronized।



✅ অনুশীলন ২: Buffered এ রূপান্তর ও পার্থক্য

package main import "fmt" func main() { ch := make(chan int, 1) ch <- 10 // এখনই send হয়ে যায়, অপেক্ষা লাগে না fmt.Println("Sent!") fmt.Println(<-ch) }

Unbuffered হলে Sent! দেখাতে receiver লাগতো 🔥। Buffered হলে sender block হয় না (buffer full না হওয়া পর্যন্ত)।


✅ অনুশীলন ৩: Channel বন্ধ করা + range

package main import "fmt" func main() { ch := make(chan int) go func() { for i := 1; i <= 5; i++ { ch <- i } close(ch) }() for v := range ch { fmt.Println(v) } }

✅ অনুশীলন ৪: 10 সংখ্যা পাঠাও এবং প্রিন্ট করো

package main import "fmt" func main() { ch := make(chan int) go func() { for i := 1; i <= 10; i++ { ch <- i } close(ch) }() for v := range ch { fmt.Println(v) } }

✅ অনুশীলন ৫: Pipeline (Generator → Doubler → Main)

package main import "fmt" func generate(ch chan int) { for i := 1; i <= 5; i++ { ch <- i } close(ch) } func double(in chan int) chan int { out := make(chan int) go func() { for v := range in { out <- v * 2 } close(out) }() return out } func main() { ch := make(chan int) go generate(ch) out := double(ch) for v := range out { fmt.Println(v) } }

🧩 চ্যালেঞ্জ প্রশ্ন (কেন deadlock হবে/হবে না?)

package main import "fmt" func main() { ch := make(chan int) ch <- 1 fmt.Println(<-ch) }

📝 Channel Rules Summary (5 Points)

  1. Channels goroutine গুলোর মধ্যে safe communication নিশ্চিত করে।
  2. Unbuffered channel send-receive synchronize করে (দুজন অপেক্ষা করে)।
  3. Buffered channel buffer capacity পর্যন্ত non-blocking send করতে দেয়।
  4. Channel বন্ধ (close(ch)) মানে আর ডেটা আসবে না; receiver range দিয়ে পড়তে পারে।
  5. Deadlock = send/receive আছে কিন্তু বিপরীত পক্ষ নেই।