1 Golang میں defer
فیچر کا تعارف
Go زبان میں، defer
کا کہنا ہے کہ اس کے بعد والی فنکشن کال کو اس وقت تک موخر کر دیا جاتا ہے جب تک defer
کا فنکشن ختم ہونے والا ہو۔ آپ اسے دوسری پروگرامنگ زبانوں میں finally
بلاک کے مترادف سمجھ سکتے ہیں، لیکن defer
کا استعمال مزید موزون اور یکتا ہے۔
defer
کے استعمال کا فائدہ یہ ہے کہ اس کو استعمال کیا جا سکتا ہے تاکہ صفائی کی تسکینات جیسے کہ فائلوں کو بند کرنا، mutexes کی آزاد کرنا، یا بس ہی فنکشن کی مخرج وقت کی داخلی کو ریکارڈ کرنا کیا جا سکے۔ یہ پروگرام کو زیادہ مضبوط بناتا ہے اور استثنائی صورتحال کے ھنڈلنگ میں پروگرامنگ کا کام کم کرتا ہے۔ Go کی ڈیزائن فلسافہ میں، defer
کے استعمال کو تجویز کیا گیا ہے کیونکہ یہ غلطیاں منظم کرتا ہے اور کوڈ کو قصر کرتا ہے، ساتھ ہی اجاگری مکمل کرنے، اور دیگر بعد کے عملات کو منظم کرتے ہوئے۔
defer
کا کام کرنے کا اصول
2.1 defer
کا بنیادی کام کرنے کا اصول
defer
کا بنیادی کام کرنے کا اصول ہے کہ ہر موخر انتظاری کرنے والے فنکشن کو چھوہدر stack (last in, first out principle) کا استعمال کرتے ہیں۔ defer
کا بیان کرنے والے سٹیشنٹ کے بعد والی فنکشن کال کو فوراً نہیں چلاتا۔ بلکہ، یہ اسے ایک علیحدہ اسٹیک میں ڈال دیتا ہے۔ صرف اس صورت میں جب باہری فنکشن واپسی کو جا رہا ہوتا ہے، یہ انتظاری فنکشن کو اسٹیک کی ترتیب میں چلاتا ہے، defer
کا آخری سٹیک کے فنکشن کو پہلے چلاتا ہے۔
اس کے علاوہ، یہ ذکر کرنا موزوں ہے کہ defer
کے بعد والی فنکشن میں پیرامیٹرز کا حساب اور مصرف defer
کے دائیں وقت کی حالت میں ثابت ہوتا ہے، وہ واقعی اجراء میں نہیں۔
func example() {
defer fmt.Println("world") // deferred
fmt.Println("hello")
}
func main() {
example()
}
اوپر دیا گیا کوڈ ایسا رزلٹ دیں گا:
hello
world
world
قبل از سامنے آتا ہے کہ example
فنکشن ختم ہوتا ہے، چاہے یہ کوڈ میں hello
سے پہلے ہو یا بعد میں۔
2.2 متعدد defer
سٹیشنٹس کا اجرائی ترتیب
جب فنکشن میں متعدد defer
سٹیشنٹس ہوتے ہیں، تو وہ آخر سے آخر، پہلے سے پہلے اجراء ہوتے ہیں۔ یہ عموماً پیچیدہ صفائی منطق کو سمجھنے کے لیے بہت اہم ہوتا ہے۔ نیچے دیے گئے مثال کی صورت میں متعدد defer
سٹیشنٹس کے اجرائی ترتیب کی وضاحت کرتے ہیں:
func multipleDefers() {
defer fmt.Println("First defer")
defer fmt.Println("Second defer")
defer fmt.Println("Third defer")
fmt.Println("Function body")
}
func main() {
multipleDefers()
}
اس کوڈ کا اوٹ پٹ یہ ہوگا:
Function body
Third defer
Second defer
First defer
defer
آخر سے آخر کے اصول کو مد نظر رکھتے ہوئے، چاہے "First defer" سب سے پہلے موخر باندھی گئی ہے، یہ سب سے آخری طور پر اجراء ہوگی۔
defer
کی مختلف سی ناریوں میں استعمال
3.1 وسائل کا خاتمہ
Go زبان میں، defer
سٹیشنٹ کو عموماً وسائل خاتمہ کے منظور کرنے کے لیے استعمال کیا جاتا ہے، جیسے فائل عملیات اور ڈیٹا بیس کنیکشن وغیرہ۔ defer
یہی یہ یقینی بناتا ہے کہ فنکشن کو ختم کرنے کے بعد، موازنہ والے وسائل کو منظم طریقے سے ختم کیا جائے گا۔
فائل کاروائی کی مثال:
func ReadFile(filename string) {
file, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
// فائل بند کرنے کو یقینی بنانے کے لیے defer استعمال کریں
defer file.Close()
// فائل کی پڑھائی کی عملیات منظم کریں...
}
اس مثال میں، جب os.Open
فائل کو کھولتا ہے، تو موازنہ والی defer file.Close()
سٹیشنٹ یہ یقین کرتا ہے کہ فائل سرسوں منظمی کی جائے گی اور فائل ہینڈل وسائل جاتے ہوئے ختم کیا جائے گا۔
ڈیٹابیس کنیکشن کی مثال:
func QueryDatabase(query string) {
db, err := sql.Open("mysql", "user:password@/dbname")
if err != nil {
log.Fatal(err)
}
// defer استعمال کرکے یقینی بنائیں کہ ڈیٹابیس کنیکشن بند ہوجائے
defer db.Close()
// ڈیٹابیس کوئری عملیات منظم کریں...
}
ایسی طرح، defer db.Close()
یہ یقینی بناتا ہے کہ QueryDatabase
فنکشن چھوڑنے کے بعد ڈیٹابیس کنیکشن بند ہو گا، چاہے وجہ واپسی ہو یا استثنائی صورتحال کو دیکھتے ہیں۔
3.2 ہم زمانہ پروگرامنگ میں لاک عملیات
ہم زمانہ پروگرامنگ میں، میوٹیکس لاکس کو آزاد کرنے کا ایک اچھا طریقہ مشق ہے۔ یہ یہ یقینی بناتا ہے کہ لاک کو درست طریقے سے آزاد کیا جاتا ہے بعد از ظروری حصہ کو چلایا جائے، ایسی طرح دیڑلاکس سے گرسے ہونے سے چھٹکارا ملتا ہے۔
میوٹیکس لاک کا مثال:
var mutex sync.Mutex
func updateSharedResource() {
mutex.Lock()
// لاک کا موقع چھوڑنے کے لئے دیفر کا استعمال کریں
defer mutex.Unlock()
// مشترکہ وسائل میں ترمیم کریں...
}
چاہے مشترکہ وسائل کی ترمیم کامیاب ہو یا دوسری چیز میں گھٹنے کے باوجود، defer
یہ یقینی بناتا ہے کہ Unlock()
کو بلا جائے گا جس سے بقایا goroutines لاک حاصل کر سکتے ہیں۔
مشورہ: میوٹیکس لاک کی تفصیلی تشریحات مواقع کے بعد درست کی جائیں گی۔ دیفر کے استعمال کے درمیان کے اطلاقات سمجھنا اس لحاظ سے کافی ہے۔
3 عام پٹھیوں اور دیفر کے لئے غور کرنے والے امور
دیفر کا استعمال کرتے وقت، چونکہ کوڈ کی پڑھائی اور ہم آہنگی بہتر ہوتی ہے، لہذا کچھ پٹھیوں اور غور وغیرہ کا خیال کرنا بھی ضروری ہے۔
3.1 دیفر کی مدد سے فنکشن کے پیرامیٹر فوراً اندازہ لگایا جاتا ہے
func printValue(v int) {
fmt.Println("Value:", v)
}
func main() {
value := 1
defer printValue(value)
// `value` کی قیمت کو بدلنا پیرامیٹر جو دیفر میں بھیجا گیا ہے پر اثر نہیں ڈالے گا
value = 2
}
// اوپر سے آؤٹپٹ "Value: 1" ہوگا
اگرچہ defer
کے اظہار کے بعد value
کی قیمت کا بدلنا ہو گیا ہے، پیرامیٹر جو printValue
میں defer
کے بعد بھیجا گیا ہے وہ پہلے ہی اندازہ لگا کر مقرر ہے، اس لئے باہر "Value: 1" ہوگا۔
3.2 لوپ کے اندر دیفر کا استعمال کرتے وقت احتیاط کریں
لوپ کی اندر دیفر کا استعمال، لوپ کے ختم ہونے سے پہلے منسلک وسائل کی رہائی نہیں کرنے کی وجہ سے وسائل کو رہا نہیں کرنا و نقصان یا استعمال سے باہر ہوسکتا ہے۔
3.3 "استعمال کے بعد رہائی" کا احتیاط کریں در متوازی پروگرامنگ
ہمزاد پروگرامنگ میں، دیفر کا استعمال کرتے وقت، یہ ضروری ہے کہ یقینی بنائیں کہ وسائل کو رہا کر دیا گیا ہے تو اس کے بعد تمام goroutines وسائل تک رسائی حاصل کرنے کی کوشش نہیں کریں گے، تاکہ واقعہ کی حالت سے بچا جائے۔
4. دیفر کے اظہارات کی اجراء کے ترتیب کا خیال کریں
دیفر کے اظہارات لیسٹ-اِن-فرسٹ (LIFO) کے اصول کا مطابق ہوتے ہیں، جس میں آخری دیفر جو اعلان کی گئی ہے وہ سب سے پہلے اجراء کی جائے گی۔
حل اور بہتری کا عمل:
- ہمیشہ دیفر بیانات میں فنکشن پیرامیٹر کو بیان کرنے وقت کا اندازہ کرنا ضروری ہے۔
- لوپ کی اندر دیفر کا استعمال کرتے ہوئے، گمنام فنکشنز یا وسائل کی رہائی کو صریح طریقے سے کال کرنا سمجھیں۔
- متوازی ماحول میں، یقینی بنائیں کہ تمام goroutines اپنے عمل ختم کرنے کے بعد ہی دیفر کے ذریعے وسائل کو رہا کریں۔
- ایسے فنکشنز لکھتے وقت جو میں کئی
defer
بیانات پر مشتمل ہوں، ان کی اجراء کی ترتیب اور منطق کو دھیان سے سوچیں۔
ان بہترین مشوروں کی پیروی سے زیادہ تر دشواریاں جو دیفر کا استعمال کرتے وقت پائی جاتی ہیں کو دور کرنا ممکن ہے اور Go کوڈ کو مضبوط اور قابل دیکھ بھال لکھنے میں کامیاب ہونے کا باعث بن سکتا ہے۔