মূল কন্টেন্টে যান
মডিউল 3 · 5-এর পাঠ 5কোর্সে 15/50~12 min
মডিউল পাঠ (5/5)

`defer`: গ্যারান্টিযুক্ত পরিষ্কার

defer একটি কল কার্যকর করা স্থগিত করে এনক্লোসিং ফাংশন পর্যন্ত ফেরত দেয়। প্যানিকের মাধ্যমে ফাংশনটি প্রস্থান করলেও এটি চলে। একাধিক defers একই ফাংশনে LIFO অর্ডারে (লাস্ট-ইন, ফার্স্ট-আউট) চালান।

এটি রিসোর্স ক্লিনআপ-এর জন্য ইডিওম্যাটিক মেকানিজম: ফাইল বন্ধ করা, মিউটেক্স আনলক করা, সংযোগ রিলিজ করা, অবস্থা পুনরুদ্ধার করা।

সিনট্যাক্স এবং ক্যানোনিকাল ব্যবহারের ক্ষেত্রে

Go
f, err := os.Open(path)
if err != nil {
    return err
}
defer f.Close()   // chiamata SEMPRE all'uscita della funzione

// ... usa f liberamente ...
return nil

সাধারণ: f.Close(), mu.Unlock(), db.Close(), tx.Rollback(), recover()

আর্গুমেন্ট অবিলম্বে মূল্যায়ন, মৃত্যুদন্ড স্থগিত

আপনি যখন defer foo(x) লেখেন, তখন x মূল্যায়ন করা হয় defer_, কার্যকর করার সময় নয়:

Go
x := 10
defer fmt.Println(x)   // cattura 10
x = 99
// quando la funzione ritorna stampa "10", non "99"

LIFO অর্ডার

সবচেয়ে সাম্প্রতিক দিয়ে শুরু করে স্ট্যাক আপ এবং এক্সিকিউট ডিফার করে:

Go
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
// output: 3, 2, 1

এটি রিসোর্স শব্দার্থবিদ্যার সাথে সামঞ্জস্যপূর্ণ: শেষ খোলা প্রথমটি বন্ধ করা

defer + recover: আতঙ্ক নিয়ন্ত্রণ করা

defer হল একটি panic বাধা দেওয়ার একমাত্র উপায়:

Go
func safe() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("recuperato:", r)
        }
    }()
    panic("boom")
}

পিটফল: defer একটি লুপে

defer f.Close() কে একটি লুপে রাখলে ** শেষ না হওয়া পর্যন্ত স্থগিত হয় ফাংশন**, প্রতিটি পুনরাবৃত্তির নয়। একটি দীর্ঘ লুপে আপনি অনেক ফাইল খুলুন এবং শুধুমাত্র যখন ফাংশন প্রস্থান করে তখনই সেগুলি বন্ধ করুন: ফাইল বর্ণনাকারী ফাঁসের ঝুঁকি৷

Go
// MALE: defer accumulati
for _, path := range paths {
    f, _ := os.Open(path)
    defer f.Close()   // chiude TUTTI alla fine della funzione esterna
    // ...
}

// MEGLIO: estrai in una funzione
for _, path := range paths {
    elabora(path)   // ogni chiamata ha il proprio scope di defer
}

চেষ্টা করে দেখুন

ব্যায়াম#go.m3.l5.e1
প্রচেষ্টা: 0লোড হচ্ছে...

'inizio' প্রিন্ট করুন, তারপর defer দিয়ে 'fine'-এর প্রিন্ট ডিফার করুন, তারপর 'mezzo' প্রিন্ট করুন। আউটপুট হতে হবে: inizio/mezzo/fine.

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

যখন main() ফিরতে চলেছে তখন defer চলে।

সমাধান 3 প্রচেষ্টার পরে উপলব্ধ

ব্যায়াম#go.m3.l5.e2
প্রচেষ্টা: 0লোড হচ্ছে...

কোডে সেই ক্রমে 1, 2 এবং 3 প্রিন্ট করে এমন তিনটি পরপর ডিফার লিখুন। আউটপুট হবে 3/2/1 (LIFO)।

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

ক্রম তিনটি defers; মনে রাখবেন তারা বিপরীত ক্রমে চালায়।

সমাধান 3 প্রচেষ্টার পরে উপলব্ধ

Quiz#go.m3.l5.e3
প্রস্তুত

এই মুদ্রণ কি? (দ্রষ্টব্য: বিলম্বিত আর্গুমেন্ট অবিলম্বে মূল্যায়ন করা হয়)

Go
x := 10
defer fmt.Println(x)
x = 99
উত্তরের বিকল্প

রিক্যাপ

  • defer call() ফাংশন ফিরে না আসা পর্যন্ত এক্সিকিউশন স্থগিত করে।
  • একাধিক ডিফার = LIFO অর্ডার।
  • যুক্তি অবিলম্বে মূল্যায়ন করা হয়েছে, মৃত্যুদন্ড স্থগিত করা হয়েছে।
  • নির্ধারক পরিষ্কারের জন্য ব্যবহৃত হয়: ফাইল, মিউটেক্স, সংযোগ।
  • defer + recover() একটি panic বাধা দেয় (বিরল, সীমানায়)।
  • একটি দীর্ঘ লুপের ভিতরে defer কখনই নয়: বাইরের ফাংশনটি ফিরে না আসা পর্যন্ত এটি জমা হয়।