1 نقشہ کی تعارف

Go زبان میں، نقشہ ایک خاص ڈیٹا ٹائپ ہے جس میں مختلف قسموں کے کلید-قیمت جوڑے محفوظ کئے جا سکتے ہیں۔ یہ پائتھن میں آئیں ڈکشنری یا جاوا میں ہیش میپ کے ساتھ مشابہ ہے۔ Go میں، نقشہ ایک بلٹ-ان ٹائپ ہے جو ہیش ٹیبل کا استعمال کرتے ہوئے حاصل کیا جاتا ہے، جس کی وجہ سے اس کے پاس تیز ڈیٹا لک اپ، اپ ڈیٹ، اور حذف کرنے کی خصوصیات ہوتی ہیں۔

خصوصیات

  • ریفرنس ٹائپ: نقشہ ریفرنس ٹائپ ہوتا ہے، جس کا مطلب ہے کہ تخلیق کے بعد، یہ عملی طور پر زیریں ڈیٹا ڈھانچے کی اشارہ حاصل کرتا ہے۔
  • متغیر توسیع: سلائس کی طرح، نقشے کا فضا ثابت نہیں ہوتا اور ڈیٹا بڑھنے سے دنامیک طریقے سے وسعت حاصل ہوتی ہے۔
  • کلیدوں کی یکتائی: نقشے میں ہر کلید یکتا ہوتا ہے، اور اگر پہلے سے موجود کلید کو ایک قیمت محفوظ کرنے کے لیے استعمال کیا جاتا ہے تو نیا قیمت پرانی کو بدل دیتا ہے۔
  • غیر مرتب سلسلہ: نقشے میں عمل کرتے وقت اراکین غیر مرتب ہوتے ہیں، لہذا کلید-قیمت جوڑوں کی ترتیب ہر بار مختلف ہو سکتی ہے جب بھی نقشہ پر چرخانا کیا جائے۔

استعمال کے مواقع

  • احصائیہ: کلیدوں کی یکتائی کا استعمال کرکے غیر تکراری اراکین کی تیزی سے شمار کریں۔
  • کیشنگ: کلید-قیمت جوڑوں کا نظام کیشنگ کے تنصیب کرنے کے لیے مناسب ہوتا ہے۔
  • ڈیٹا بیس کنیکشن پول: ڈیٹا بیس کنیکشن جیسے وسائل کا انتظام کریں، جو وسائل کو شیئر کرنے اور مختلف گاہکوں کے ذریعہ رسائی حاصل کرنے کی اجازت دیتا ہے۔
  • تشکیلی اشیاء ذخیرہ: تشکیلی فائلوں سے پیرامیٹرز کو ذخیرہ کرنے کے لیے استعمال ہوتا ہے۔

2 نقشہ بنانا

2.1 make فعل کے ساتھ بنانا

نقشہ بنانے کا سب سے عام طریقہ make فعل کا استعمال ہے، جس کا حسب سے مندرجہ ذیل سینٹیکس ہوتا ہے:

make(map[keyType]valueType)

یہاں، keyType کلید کی قسم ہے، اور valueType قیمت کی قسم ہے۔ یہاں ایک مخصوص استعمال کا مثال ہے:

// ایک نقشہ بنانا جس میں کلید کی قسم سٹرنگ ہے اور قیمت کی قسم عدد صحیح ہے
m := make(map[string]int)

اس مثال میں ہم نے ایک خالی نقشہ بنایا ہے جو کہ سٹرنگ کلید اور عدد صحیح قیمتوں کو ذخیرہ کرنے کے لیے استعمال ہوگا۔

2.2 حرفی طرز میں ساخت

make کے علاوہ، ہم حرفی طرز کا استعمال کرکے بھی ایک نقشہ بنا سکتے ہیں، جو عینی طور پر ایک ساتھ کئی کلید-قیمت جوڑوں کا اعلان کرتا ہے۔

m := map[string]int{
    "apple": 5,
    "pear": 6,
    "banana": 3,
}

یہ نقشہ نہ صرف بناتا ہے بلکہ اس کے لیے تین کلید-قیمت جوڑے بھی ترتیب کرتا ہے۔

2.3 نقشہ کی تشکیل کے لئے غور کرنا

نقشے کا استعمال کرتے ہوئے، اہم ہے کہ غیر تشکیل یافتہ نقشے کی صفر قیمت nil ہوتی ہے، اور اس لمحے میں آپ نے اس میں کسی بھی عمل کی ہوا۔ آپ کو پہلے اسے تشکیل دینے کے لیے make کا استعمال کرنا ہوگا:

var m map[string]int
if m == nil {
    m = make(map[string]int)
}
// اب m استعمال کرنا محفوظ ہے

اس کے علاوہ، نقشے میں کسی کلید کے وجود کی تصدیق کے لئے ایک خاص سنٹیکس بھی ہے:

value, ok := m["key"]
if !ok {
    // "key" نقشے میں نہیں ہے
}

یہاں، value دی جانے والی کلید کے ساتھ منسلک قیمت ہے، اور ok ایک بولین قیمت ہے جو اگر نقشے میں کلید موجود ہو تو ٹرو ہوگی اور اگر نہیں تو فالس۔

3 نقشے تک رسائی اور ترتیب دینا

3.1 اراکین تک رسائی

Go زبان میں، آپ نقشے میں کسی کلید کے ساتھ منسلک قیمت تک رسائی حاصل کر سکتے ہیں۔ اگر کلید نقشے میں موجود ہو تو، آپ دی گئی قیمت حاصل کریں گے۔ لیکن اگر کلید موجود نہ ہو تو، آپ کو قیمت کی قیمت کی صفر قیمت ملے گی۔ مثال کے طور پر، اگر نقشہ میں عدد صحیح محفوظ کیا ہوا ہے، تو اگر کلید نقشہ میں نہیں ہوتا تو یہ صفر کو واپس کرے گا۔

func main() {
    // نقشہ کا تعرف کرنا
    scores := map[string]int{
        "Alice": 92,
        "Bob": 85,
    }

    // موجودہ کلید تک رسائی
    aliceScore := scores["Alice"]
    fmt.Println("Alice's score:", aliceScore) // Output: Alice's score: 92

    // غیر موجودہ کلید تک رسائی
    missingScore := scores["Charlie"]
    fmt.Println("Charlie's score:", missingScore) // Output: Charlie's score: 0
}

نوٹ کریں کہ حتی کہ کلید "Charlie" نقشے میں موجود نہیں ہوتی ہے، یہ ایک خرابی کو نہیں پیدا کرے گا، بلکہ بدلہ میں عدد صحیح کی صفر قیمت، 0، واپس کرے گا۔

3.2 کلید کی موجودگی کا جانچ

کبھی کبھار ہم صرف یہ جاننا چاہتے ہیں کہ کیا ایک میپ میں کوئی خصوصی کلید موجود ہے یا نہیں، اس کے مطابقتی قیمت سے غیر دوںت کرتے ہوئے۔ ایسی صورت میں، آپ میپ دسترسی کے دوسرے واپسی قیمت کا استعمال کر سکتے ہیں۔ یہ بولین واپسی قیمت ہمیں بتائے گی کہ کیا کلید میپ میں موجود ہے یا نہیں۔

func main() {
    scores := map[string]int{
        "Alice": 92,
        "Bob": 85,
    }

    // Checking if the key "Bob" exists
    score, exists := scores["Bob"]
    if exists {
        fmt.Println("Bob's score:", score)
    } else {
        fmt.Println("Bob's score not found.")
    }

    // Checking if the key "Charlie" exists
    _, exists = scores["Charlie"]
    if exists {
        fmt.Println("Charlie's score found.")
    } else {
        fmt.Println("Charlie's score not found.")
    }
}

اس مثال میں، ہم ایک if بیان استعمال کرتے ہیں تاکہ ہم بولین قیمت کی جانچ کر سکیں کہ کیا کوئی کلید موجود ہے یا نہیں۔

3.3 عناصر شامل اور اپ ڈیٹ کرنا

نیا عنصر میپ میں شامل کرنا اور موجودہ عنصر کو اپ ڈیٹ کرنا دونوں میں یہی ہوتا ہے. اگر کلید پہلے سے موجود ہوتا ہے تو پہلی قیمت نئی قیمت سے بدل دی جائے گی۔ اگر کلید موجود نہیں ہوتا ہے، تو نیا کلید-قیمت جوڑ شامل ہو جائے گا۔

func main() {
    // Define an empty map
    scores := make(map[string]int)

    // Adding elements
    scores["Alice"] = 92
    scores["Bob"] = 85

    // Updating elements
    scores["Alice"] = 96  // Updating an existing key

    // Print the map
    fmt.Println(scores)   // Output: map[Alice:96 Bob:85]
}

شامل اور اپ ڈیٹ کرنے کے عمل خلاصے ہیں اور انہیں بنیادی اسائنمنٹ کی مدد سے پورا کیا جا سکتا ہے۔

3.4 عناصر مٹانا

میپ سے عناصر کو ہٹانا موجودہ delete تفاوت کا استعمال کر کے کیا جا سکتا ہے۔ مندرجہ ذیل مثال شامل کرتی ہے:

func main() {
    scores := map[string]int{
        "Alice": 92,
        "Bob": 85,
        "Charlie": 78,
    }

    // Delete an element
    delete(scores, "Charlie")

    // Print the map to ensure Charlie is deleted
    fmt.Println(scores)  // Output: map[Alice:92 Bob:85]
}

delete کا استعمال دو مقداریں لیتا ہے، پہلی مقدار کو میپ خود اور دوسری مقدار کو ڈیلیٹ کرنے والی کلید کے طور پر لیتا ہے۔ اگر کلید میپ میں موجود نہیں ہوتا ہے تو delete تفاوت کا کوئی اثر نہیں ہوتا اور نہ ہی کوئی خرابی ہوتی ہے۔

4 ایک میپ کا دورانیہ کرنا

Go زبان میں، آپ میپ ڈیٹا ساختار کا دورانیہ کرنے اور ہر ایک کلید-قیمت جوڑ کو دسترس دینے کے لئے for range بیان کا استعمال کر سکتے ہیں۔ یہ نوعیت کا لوپ دورانیہ کو مدد کرنے والا بنیادی عمل ہے جو میپ ڈیٹا ساختار کے ساتھ موزوں ہوتا ہے۔

4.1 for range کا استعمال کرکے میپ پر چلنا

for range بیان کو سیدھے طور پر ایک میپ پر استعمال کیا جا سکتا ہے تاکہ ہم میپ میں ہر ایک کلید-قیمت جوڑ تک پہنچ سکیں۔ نیچے دی گئی مثال ہے:

package main

import "fmt"

func main() {
    myMap := map[string]int{"Alice": 23, "Bob": 25, "Charlie": 28}

    for key, value := range myMap {
        fmt.Printf("Key: %s, Value: %d\n", key, value)
    }
}

اس مثال میں، key متغیر کو موجودہ دورانیہ کی کلید سے منسلک کیا جاتا ہے، اور value متغیر وہ قیمت منسلک ہوتی ہے جو اس کلید سے منسلک ہوتی ہے۔

4.2 دورانیہ کے ترتیب کے بارے میں تاثرات

اس بات کا نوٹس لینا اہم ہے کہ جب میپ پر دورانیہ کرتے ہیں تو دورانیہ کے ترتیب کی ضمانت ہر بار یکساں نہیں ہوتی، حتی کہ اگر میپ کا مواد تبدیل نہیں ہوا ہو۔ یہ اس وجہ سے ہے کہ Go میں میپ پر دورانیہ کا عمل بے تسلسل ہوتا ہے تاکہ پروگرام کسی خاص دورانیہ کے ترتیب پر اہلان کو موانع نہ وجود کرے، اس طرح کوڈ کی محکمی بہتر ہوتی ہے۔

مثال کے طور پر، نیچے دی گئی کوڈ کو دو بار لوٹانے سے مختلف نتائج حاصل ہو سکتے ہیں:

package main

import "fmt"

func main() {
    myMap := map[string]int{"Alice": 23, "Bob": 25, "Charlie": 28}

    fmt.Println("First iteration:")
    for key, value := range myMap {
        fmt.Printf("Key: %s, Value: %d\n", key, value)
    }

    fmt.Println("\nSecond iteration:")
    for key, value := range myMap {
        fmt.Printf("Key: %s, Value: %d\n", key, value)
    }
}

نقشہ پر پانچ انتہائی مشکل موضوعات

اب ہم نقشوں سے متعلق مختلف پیشگی موضوعات پر غور کریں گے جو آپ کو نقشوں کو بہتر انداز میں سمجھنے اور استعمال کرنے میں مدد فراہم کر سکتے ہیں۔

5.1 نقشوں کی یاداشت اور کارکردگی کی خصوصیات

Go زبان میں، نقشے بہت ذراعت اورطاقتور ڈیٹا قسم ہیں، لیکن ان کی متغیرت کی وجہ سے ان کی یادگاری اور کارکردگی کے خصوصیات بھی واضح ہوتی ہیں۔ مثال کے طور پر، نقشے کا سائز دوبارہ بہتتر [مانتر] (memory) کا تصور کرنے سے بھی بھاری ہوسکتا ہے، اور جب اس میں محفوظ عناصر کی تعداد موجودہ سکت سے زیادہ ہو تو، نقشہ انتہائی وسعتی خالی جگہ میں دوبارہ منصوبہ بندی کر کے بڑھائی گی۔

یہ دوبارہ منصوبہ بندی وسعت کے باعث کارکردگی مسائل کا سبب بن سکتی ہے، خصوصاَ وقت جب بڑے نقشوں یا کارکردگی پر مبنی اطلاق کے لئے۔ کارکردگی کو بہتر بنانے کے لئے، نقشے بناتے وقت زمین وسعت کا معقول ابتدائی فضا تعین کر سکتے ہیں۔ مثال کے طور پر:

myMap := make(map[string]int, 100)

یہ نقشے کی دوبارہ منصوبہ بندی کے وقت زمین بڑھانے کے عائشے کے نقصان کو کم کر سکتی ہے۔

5.2 نقشوں کی حوالہ قسم کی خصوصیات

نقشے حوالے کی قسم ہیں، یعنی جب آپ ایک نقشہ کو دوسرے متغیر کو تفویض کرتے ہیں، تو نیا متغیر اصل نقشے کا سامانی ڈیٹا ساخت کو حوالہ کرے گا۔ یہ بھی ماتحت نقشے کو نئے متغیر کے ذریعے تبدیل کرنے کی صورت میں شامل ہوتا ہے یہ بھی ماتحت شامل ہے کہ اگر آپ نقشے کو نئے متغیر کے ذریعے تبدیل کریں تو یہ تبدیلیاں اصل نقشے متغیر میں دکھائی دیں گی۔ یہاں ایک مثال ہے:

package main

import "fmt"

func main() {
    originalMap := map[string]int{"Alice": 23, "Bob": 25}
    newMap := originalMap

    newMap["Charlie"] = 28

    fmt.Println(originalMap) // یہ اوٹ پٹ نئے شامل شدہ "Charlie": 28 کلید-قیمت جوڑ کو دکھائی گی
}

جب نقشے کو فراہم کرنے والے کردار پہ بھی رجعت نقشے کی روایتی خصوصیات پر نظر رکھنا بھی اہم ہے۔ اس لحاظ سے، جو شئے فراہم کیا گیا ہے، وہ نقشے کی حوالے کی قسم کا حوالہ ہے، نہ کوپی کا.

5.3 متناسب معاونت اور sync.Map

نقشے کا استعمال بیک وقتی ماحول میں، متناسب معاونتی مسائل پر خصوصی توجہ دیتے ہوئے ان جوزات کو دیکھا جاتا ہے۔ بیک وقتی منظر میں، Go کی معیاری لائبریری 'sync.Map' قسم فراہم کرتی ہے جو کہ بیک وقتی ماحول کے لئے بنائی گئی ایک محفوظ نقشہ ہے۔ یہ قسم بنیادی تراکیب مثل Load, Store, LoadOrStore, Delete، اور Range فراہم کرتی ہے تاکہ نقشے پر عمل کرے۔

نیچے 'sync.Map' کا استعمال کرتے وقت مثال دی گئی ہے۔

package main

import (
    "fmt"
    "sync"
)

func main() {
    var mySyncMap sync.Map

    // کلید-قیمت جوڑ جمع کرنا
    mySyncMap.Store("Alice", 23)
    mySyncMap.Store("Bob", 25)

    // کلید-قیمت جوڑ کو حاصل کرنا اور چھاپنا
    if value, ok := mySyncMap.Load("Alice"); ok {
        fmt.Printf("Key: Alice, Value: %d\n", value)
    }

    // sync.Map کے ذریعے گزرنے کا طریقہ استعمال کرکے
    mySyncMap.Range(func(key, value interface{}) bool {
        fmt.Printf("Key: %v, Value: %v\n", key, value)
        return true // گزرنا جاری رکھنا
    })
}

عام نقشے کی بجائے 'sync.Map' کا استعمال بیک وقتی ماحول میں نقشے کو ترتیب دینے والی مسائل سے بچا سکتا ہے، اور اس طرح رہائشی مسائل کو یقینی بنا سکتا ہے۔