Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

الـ Pointers كقيم في الـ Maps

جزء من قسم Logic & Flow في رحلة GO على Coddy — الدرس 27 من 68.

بينما يعد تخزين الـ structs مباشرة في الـ maps أمراً مفيداً، فإن تخزين المؤشرات (pointers) إلى الـ structs يفتح إمكانية قوية: القدرة على تعديل بيانات الـ struct الأصلية مباشرة من خلال الـ map. هذا النهج ضروري عندما تحتاج إلى تحديث بياناتك بعد تخزينها.

عندما تقوم بتخزين مؤشر (pointer) إلى هيكل (struct) كقيمة في خريطة (map)، فإنك تقوم بتخزين عنوان الذاكرة للهيكل، وليس نسخة منه. إليك كيفية التصريح عن مثل هذه الخريطة والتعامل معها:

type Product struct {
    Price    float64
    Quantity int
}

products := map[string]*Product{
    "laptop": &Product{Price: 999.99, Quantity: 5},
    "mouse":  &Product{Price: 25.50, Quantity: 20},
}

تتضح الميزة الأساسية عندما تحتاج إلى تعديل البيانات. نظرًا لأنك تتعامل مع المؤشرات (pointers)، فإن التغييرات التي يتم إجراؤها من خلال الخريطة (map) تؤثر على الهيكل (struct) الأصلي:

// تحديث سعر الكمبيوتر المحمول مباشرة من خلال الخريطة
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // يطبع: 899.99

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

quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

challenge icon

التحدي

سهل

قم ببناء نظام بسيط لإدارة المخزون يوضح قوة استخدام المؤشرات (pointers) لهياكل البيانات (structs) كقيم في الخرائط (maps). يوضح هذا التحدي كيف تمكن الخرائط القائمة على المؤشرات من التعديل المباشر للبيانات المخزنة، مما يجعل نظام المخزون الخاص بك فعالاً وسريع الاستجابة للتحديثات.

ستتلقى ثلاثة مدخلات:

  • سلسلة نصية تمثل عدد المنتجات (مثلاً، "4")
  • سلسلة نصية تحتوي على بيانات المنتج بالتنسيق التالي: "name1:price1:quantity1,name2:price2:quantity2,name3:price3:quantity3" (مثلاً، "laptop:999.99:5,mouse:25.50:20,keyboard:75.00:15,monitor:299.99:8")
  • سلسلة نصية تحتوي على عمليات التحديث بالتنسيق التالي: "operation1:product1:value1,operation2:product2:value2" حيث تكون العمليات إما "price" أو "quantity" (مثلاً، "price:laptop:899.99,quantity:mouse:25,price:keyboard:65.00")

مهمتك هي:

  1. تعريف هيكل Product بالحقول التالية:
    • Price (float64) - سعر المنتج
    • Quantity (int) - كمية المخزون للمنتج
  2. إنشاء خريطة (map) حيث تكون المفاتيح هي أسماء المنتجات (strings) والقيم هي مؤشرات (pointers) لهياكل Product
  3. تحليل بيانات المنتج من المدخل الثاني:
    • تقسيم المدخل بواسطة الفواصل للحصول على إدخالات المنتجات الفردية
    • لكل إدخال، قم بالتقسيم بواسطة النقطتين الرأسيتين لفصل الاسم والسعر والكمية
    • تحويل سلسلة السعر النصية إلى float64 وسلسلة الكمية النصية إلى عدد صحيح (integer)
    • إنشاء هيكل Product وتخزين مؤشر له في الخريطة
  4. عرض المخزون الأولي مع العنوان "Initial Inventory:"
  5. إظهار كل منتج بالتنسيق التالي: "[name]: $[price] (Stock: [quantity])"
  6. تحليل وتطبيق عمليات التحديث من المدخل الثالث:
    • تقسيم المدخل بواسطة الفواصل للحصول على العمليات الفردية
    • لكل عملية، قم بالتقسيم بواسطة النقطتين الرأسيتين للحصول على نوع العملية، واسم المنتج، والقيمة الجديدة
    • تحديث الحقل المناسب مباشرة من خلال مؤشر الخريطة
    • طباعة كل تحديث بالتنسيق التالي: "Updated [product]: [field] changed to [new_value]"
  7. عرض المخزون المحدث مع العنوان "Updated Inventory:"
  8. إظهار كل منتج مرة أخرى بنفس تنسيق العرض الأولي
  9. حساب وعرض القيمة الإجمالية للمخزون: "Total Inventory Value: $[total_value]"

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

ورقة مرجعية

يمكن للخرائط (Maps) تخزين مؤشرات إلى الهياكل (structs)، مما يسمح بالتعديل المباشر لبيانات الهيكل الأصلي من خلال الخريطة:

type Product struct {
    Price    float64
    Quantity int
}

products := map[string]*Product{
    "laptop": &Product{Price: 999.99, Quantity: 5},
    "mouse":  &Product{Price: 25.50, Quantity: 20},
}

عند استخدام المؤشرات كقيم للخريطة، فإن التعديلات التي تتم من خلال الخريطة تؤثر على الهيكل الأصلي:

// تحديث سعر الكمبيوتر المحمول مباشرة من خلال الخريطة
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // يطبع: 899.99

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

جرّب بنفسك

package main

import (
	"fmt"
	"strconv"
	"strings"
)

func main() {
	// قراءة المدخلات
	var numProductsStr string
	var productDataStr string
	var operationsStr string
	
	fmt.Scanln(&numProductsStr)
	fmt.Scanln(&productDataStr)
	fmt.Scanln(&operationsStr)
	
	// TODO: قم بتعريف هيكل المنتج (Product struct) هنا
	
	// TODO: قم بإنشاء خريطة (map) لتخزين مؤشرات المنتجات
	
	// TODO: قم بإنشاء شريحة (slice) للحفاظ على ترتيب المنتجات (لضمان مخرجات متسقة)
	
	// TODO: قم بتحليل بيانات المنتج وملء الخريطة
	// تذكر أن تقوم بـ:
	// - تقسيم productDataStr بواسطة الفواصل للحصول على المدخلات الفردية
	// - لكل مدخل، قم بالتقسيم بواسطة النقطتين الرأسيتين للحصول على الاسم والسعر والكمية
	// - تحويل سلاسل السعر والكمية إلى الأنواع المناسبة
	// - تخزين مؤشر لهيكل المنتج في الخريطة
	// - إضافة اسم المنتج إلى شريحة الترتيب
	
	// TODO: عرض المخزون الأولي
	// استخدم شريحة الترتيب للتكرار عبر المنتجات بشكل متسق
	// التنسيق: "[name]: $[price] (Stock: [quantity])"
	
	// TODO: تحليل وتطبيق عمليات التحديث
	// تذكر أن تقوم بـ:
	// - تقسيم operationsStr بواسطة الفواصل للحصول على العمليات الفردية
	// - لكل عملية، قم بالتقسيم بواسطة النقطتين الرأسيتين للحصول على النوع والاسم والقيمة
	// - تحديث الحقل المناسب مباشرة من خلال مؤشر الخريطة
	// - طباعة رسالة تحديث لكل عملية
	
	// TODO: عرض المخزون المحدث
	// مرة أخرى، استخدم شريحة الترتيب للحصول على مخرجات متسقة
	// احسب القيمة الإجمالية أثناء العرض
	
	// TODO: حساب وعرض القيمة الإجمالية للمخزون
	// التنسيق: "Total Inventory Value: $[total_value]"
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Logic & Flow