محتويات الدورة

Go / الأساسي: القيم وعقود البرامج / الدرس 5

الخرائط والبنى وثوابت البيانات

اختر البحث بالمفتاح والسجلات عمدا واحفظ الثوابت دون اختراع ترتيب للخرائط أو نسخ عميق.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • استخدام بحث الخريطة مع معلومة الوجود.
  • إنتاج إخراج حتمي دون الاعتماد على ترتيب الاجتياز.
  • شرح نسخ البنى المحتوية على حقول مرجعية.

الخريطة تربط مفاتيح قابلة للمقارنة بقيم

توفر الخريطة وصولا بالمفتاح لا ترتيبا موضعيا. يجب أن يكون نوع المفتاح قابلا للمقارنة؛ وليست الشرائح والخرائط والدوال مفاتيح عادية قابلة لها. يعيد البحث الغائب القيمة الصفرية لنوع العنصر. استخدم value, ok := m[key] لتمييز الصفر المخزن من الغياب. تبلغ len عدد العناصر لا السعة المخصصة.

تدعم خريطة nil البحث والطول والاجتياز والحذف لكن إسناد عنصر يسبب هلعا. هيئ القابلة للكتابة بـmake أو تعبير خريطة. يشارك نسخ قيمة الخريطة بياناتها لا يكررها مستقلة. ويحتاج الوصول المتزامن سياسة عندما قد تتداخل كتابة مع وصول آخر.

ترتيب المفاتيح عندما يهم ترتيب الإخراج

ترتيب اجتياز الخريطة غير محدد ولا يضمن الثبات بين اجتيازين. وليس واجهة أعداد عشوائية ولا خلطا مضمونا. يجمع المثال المفاتيح ويرتبها ثم يبحث بالترتيب الصريح.

في خريطة أسماء إلى أعداد يختلف الاسم الغائب عن عدد صفر مخزن. يكشف بحث comma-ok الفرق قبل الإخراج. وإذا تغيرت البيانات بالتزامن فلا يجعل ترتيب لقطة المفاتيح القراءات التالية آمنة؛ يجب أن تغطي المزامنة أو ملكية اللقطة العملية كاملة.

go تمثيل ثابت لبيانات غير مرتبة
package main

import (
	"fmt"
	"sort"
)

func main() {
	counts := map[string]int{"pear": 2, "apple": 0}
	_, present := counts["missing"]
	keys := make([]string, 0, len(counts))
	for key := range counts {
		keys = append(keys, key)
	}
	sort.Strings(keys)
	for _, key := range keys {
		fmt.Printf("%s=%d\n", key, counts[key])
	}
	fmt.Println("missing present", present)
}
الناتج المتوقع
apple=0
pear=2
missing present false

يثبت الفرز apple قبل pear؛ ويبلغ البحث الغائب false.

السجل يربط الحقول منطقيا

تجمع struct حقولا مسماة قد تختلف أنواعها. توضح التعابير المركبة المسماة القصد وتبقي الحقول المحذوفة صفرية. تبدأ المعرفات المكشوفة بحرف كبير، لكن كشف التخزين يسمح بتجاوز التحقق. أبق الحقول ذات الثوابت خاصة عندما يجب مرور التغييرات بعملية.

في حجز يجب ألا تأتي البداية بعد النهاية. وفي مخزن لا يتجاوز الطول المنطقي السعة. تعرف العلاقات حالات صالحة تتجاوز نوع كل حقل. يجب أن تحفظ المنشئات والطرق المعدلة هذه العلاقات، وأن يترك الفشل حالة موثقة لا تحديثا جزئيا.

إسناد البنية ينسخ قيم الحقول

ينسخ المثال التالي سجلا يحتوي نصا وشريحة. يغير استبدال copy.Name الحقل النصي المنسوخ فقط، بينما يصل copy.Scores[0] للمصفوفة المشتركة. الإسناد نسخ قيمة كامل للبنية؛ وتبقى المشاركة لأن حقل الشريحة المنسوخ نفسه يصف تخزينا موجودا.

تنطبق القاعدة أيضا على الخرائط والمؤشرات داخل السجلات. لا يمنح المنشئ تلقائيا ملكية حصرية للمجموعات المقدمة. اختر استعارة المدخل أو تحمل مسؤولية ملكية بالاصطلاح أو النسخ. وثق الاختيار واختبر التعديلات من الجانبين.

go قد تصف الحقول المنسوخة تخزينا مشتركا
package main

import "fmt"

type Record struct {
	Name   string
	Scores []int
}

func main() {
	original := Record{Name: "Ada", Scores: []int{1, 2}}
	copied := original
	copied.Name = "Bo"
	copied.Scores[0] = 9
	fmt.Println(original.Name, original.Scores, copied.Name, copied.Scores)
}
الناتج المتوقع
Ada [9 2] Bo [9 2]

الاسمان قيمتا حقل مستقلتان بينما تبقى الدرجات مشتركة.

تبسيط سياسات التعديل

أثناء range على الخريطة لا يظهر عنصر حُذف قبل بلوغه؛ وقد يظهر أو لا يظهر عنصر أُنشئ أثناء الاجتياز. لا تبن معالجة أساسية على هذه البدائل. اجمع قائمة عمل أو افصل مرحلة التحديث عند الحاجة إلى نتيجة واضحة تشبه اللقطة.

ليس عنصر الخريطة متغير بنية يمكن أخذ عنوانه؛ ولا يسمح عموما بتعديل حقل بنيته مباشرة. اجلب القيمة وعدلها وأعدها، أو خزّن مؤشرات عمدا بسياسة مشاركة واضحة. يغير تخزين المؤشرات مسائل العمر والتزامن، وليس مجرد حيلة صياغية.

الأخطاء الشائعة وإصلاحها

يُعامل صفر مخزن كمفتاح غائب.

لماذا يحدث؟
تجاهل البحث نتيجة الوجود.
كيف تصلحه؟
استخدم صيغة comma-ok.
كيف تتجنب تكراره؟
اختبر الغائب والصفر المخزن.

يتغير ترتيب الإخراج بين التشغيلات.

لماذا يحدث؟
اعتُبر range للخريطة عقد ترتيب.
كيف تصلحه؟
رتب المفاتيح أو استخدم تمثيلا مرتبا.
كيف تتجنب تكراره؟
اجعل الترتيب صريحا في الاختبارات والتسلسل.

يغير سجل منسوخ مجموعة سجل آخر دون توقع.

لماذا يحدث؟
ما زال حقل الشريحة أو الخريطة مشتركا.
كيف تصلحه؟
انسخ البيانات المشار إليها عند الحاجة للعزل.
كيف تتجنب تكراره؟
وثق مشاركة المنشئات والنسخ.

اختبر فهمك

1. تخزن خريطة أرصدة ويصح الصفر. صمم بحثا يميز الحساب المجهول.

اعرض الحل المشروح

أعد الرصيد وعلم وجود أو حول الغياب لخطأ موثق. استخدم comma-ok لا balance == 0. اختبر الغائب والصفر المخزن ورصيدا موجبا. إذا شاركها كتاب فاحم البحث بسياسة مزامنة التحديثات نفسها.

2. كيف تجعل Scores في Record المنسوخ مستقلة مع حفظ Name؟ وضح حد البيانات المتداخلة.

اعرض الحل المشروح

انسخ السجل ثم أسند copied.Scores = append([]int(nil), original.Scores...). تصبح عناصر int في تخزين منفصل فلا يؤثر تعديلها في الأخرى. والحقل النصي ثابت كقيمة أصلا. أما لو احتوت Scores شرائح أو مؤشرات فلا يكرر النسخ الخارجي أهدافها تكرارا عميقا.

أهم ما تعلمته

  • الوجود والقيمة وترتيب الإخراج مسائل خريطة منفصلة.
  • تربط ثوابت البنية الحقول بما يتجاوز أنواعها.
  • قد يشمل نسخ القيمة أوصاف تخزين مشترك.

المراجع الرسمية