ক্লাস ২৬: ক্লোজার এবং Go এর অভ্যন্তরীণ মেমোরি গভীর বিশ্লেষণ 💡
এই ক্লাসে আমরা closure, escape analysis নিয়ে বিস্তারিত পড়াশুনা করব এবং অভ্যন্তরীণ মেমরি কিভাবে মেনেজ করা হয় তা জানব! 🧠🔥
📋 ক্লাস ২৬ এর কোড:
package main
import "fmt"
const a = 10
var p = 100
//Closure
func outer(money int) func() {
age := 30
fmt.Println("Age =", age)
show := func() {
money = money + a + p
fmt.Println(money)
}
return show
}
func call() {
incr1 := outer(100)
incr1() // money = 100 + 10 + 100 = 210
incr1() // money = 210 + 10 + 100 = 320
incr2 := outer(100)
incr2()
incr2()
}
func main() {
call()
}
func init() {
fmt.Println("=== Bank ===")
}
🔍 মূল বিষয়বস্তু
🔒ক্লোজার (Closure) কী?
ক্লোজার এমন একটি ফাংশন যা তার নিজস্ব স্কোপের বাইরের ভেরিয়েবলগুলোর সাথে সম্পর্ক স্থাপন করতে পারে। এই ক্ষেত্রে:
show := func() {
money = money + a + p
fmt.Println(money)
}
show
ফাংশনটি outer()
ফাংশনের ভেতরের money
ভেরিয়েবলটি মনে রাখার মাধ্যমে একটি ক্লোজার তৈরি করে।
🧠 ক্লোজার কেন গুরুত্বপূর্ণ?
ক্লোজার যুক্তি ও অবস্থাকে একসাথে ধরে রাখতে সাহায্য করে। এজন্য incr1()
এবং incr2()
একই ফাংশন ব্যবহার করলেও আলাদা money
মান ধরে রাখতে পারে।
🧮 স্ট্যাক বনাম হিপ
স্ট্যাক: দ্রুত মেমোরি, ফাংশন কল এবং লোকাল ভেরিয়েবলের জন্য ব্যবহৃত হয়।
হিপ: যখন ভেরিয়েবল ফাংশন কলের পরেও থাকা দরকার (যেমন ক্লোজারে), তখন ব্যবহৃত হয়।
money
ফাংশন outer()
শেষ হওয়ার পরও থাকতে হবে, তাই এস্কেপ অ্যানালাইসিস এটা বুঝে money
হিপে রাখে।
🧪 এস্কেপ অ্যানালাইসিস (Escape Analysis) কী?
এস্কেপ অ্যানালাইসিস হলো একটি প্রক্রিয়া যার মাধ্যমে Go কম্পাইলার ফাংশনগুলো কম্পাইল করার সময় বুঝতে পারে কোন ভেরিয়েবল স্ট্যাকে নিরাপদে রাখা যাবে আর কোনগুলো হিপে পাঠাতে হবে।
- ✅ যদি কোনো ভেরিয়েবল শুধুমাত্র ফাংশনের ভেতর ব্যবহার হয়, তাহলে সেটি স্ট্যাকে রাখা হয়।
- 🚀 যদি কোনো ভেরিয়েবল ফাংশনের বাইরে (যেমন একটি রিটার্ন করা ক্লোজারে) ব্যবহার হয়, তাহলে সেটি হিপে স্থানান্তরিত হয়।
🧱 মেমোরি সেগমেন্ট
সেগমেন্ট | কী সংরক্ষণ করে |
---|---|
কোড সেগমেন্ট | কম্পাইল করা নির্দেশাবলী এবং কনস্ট্যান্ট (ফাংশন, a ) |
ডেটা সেগমেন্ট | গ্লোবাল ভেরিয়েবল (p ) |
স্ট্যাক | লোকাল ভেরিয়েবল (age ) |
হিপ | এস্কেপিং ভেরিয়েবল (money ) |
🧠 ভিজ্যুয়ালাইজেশন
CLI-স্টাইল মেমোরি বিন্যাস
┌─────────────────────────────┐
│ কোড সেগমেন্ট │
│-----------------------------│
│ const a = 10, |
| main, call, init, outer, │
│ anonymous show function │
└─────────────────────────────┘
↓
┌─────────────────────────────┐
│ ডেটা সেগমেন্ট │
│-----------------------------│
│ var p = 100 │
└─────────────────────────────┘
↓
┌─────────────────────────────┐
│ স্ট্যাক │
│-----------------------------│
│ outer() frame │
│ age = 30 │
│ return address │
└─────────────────────────────┘
↓
┌─────────────────────────────┐
│ হিপ │
│-----------------------------│
│ money = 100 (for incr1) │
│ money = 100 (for incr2) │
└─────────────────────────────┘
প্রতিটি ক্লোজারের জন্য হিপে নিজস্ব money
থাকে। প্রতিবার outer(100)
কল করার সময় একটি নতুন মেমোরি ব্লক অ্যালোকেট করা হয়।
গারবেজ কালেক্টরের ভূমিকা 🧹
যখন কোনো ক্লোজার আর রেফারেন্স করা হয় না (যেমন incr1
বা incr2
স্কোপের বাইরে চলে যায়), তখন গারবেজ কালেক্টর
সেই হিপ মেমোরি (যেমন money
) মুছে ফেলে, যাতে অপ্রয়োজনীয় মেমোরি দখল না থাকে। অনেক ক্লোজার থাকলে কর্মদক্ষতা বজায় রাখতে এটা খুবই গুরুত্বপূর্ণ।
GC স্বয়ংক্রিয়ভাবে ট্রিগার হয় এবং প্রোগ্রামের সাথে একযোগে চলে। এটি কার্যকরভাবে কাজ করার জন্য mark-and-sweep এবং concurrent garbage collection techniques ব্যবহার করে।
🧠 সংক্ষেপে
- ক্লোজার ভেরিয়েবলের অবস্থা ধরে রাখতে পারে 🔁
- এস্কেপ অ্যানালাইসিস নির্ধারণ করে কোন ভেরিয়েবল হিপে রাখা প্রয়োজন 📦
- স্ট্যাক সাময়িক, হিপ স্থায়ী (GC 🧹 এর সাথে)
- Go মেমোরি চারটি ভাগে ভাগ করে: কোড, ডেটা, স্ট্যাক, হীপ 🧩
- GC অপ্রচলিত হীপ মেমোরি পুনর্ব্যবহারযোগ্য করে তোলে ♻️
[Author: @ifrunruhin12, @nazma98 Date: 2025-05-01 - 2025-05-17 Category: interview-qa/class-wise ]