البرمجة

المصفوفات والشرائح في Go

المصفوفات (Arrays) والشرائح (Slices) في لغة Go: مقدمة شاملة

تعتبر المصفوفات (Arrays) والشرائح (Slices) من الهياكل البيانية الأساسية في لغة البرمجة Go، وهما من الأدوات الحاسمة التي يتم استخدامها بشكل متكرر في العديد من التطبيقات البرمجية. على الرغم من أن كليهما يُستخدم لتخزين مجموعات من البيانات، إلا أنهما يختلفان في طريقة استخدامهما وخصائصهما. في هذا المقال، سنستعرض مفهوم المصفوفات والشرائح في لغة Go، مع توضيح الفرق بينهما وأسلوب التعامل مع كل منهما.

المصفوفات (Arrays) في لغة Go

في البداية، من المهم أن نفهم كيفية عمل المصفوفات في Go. المصفوفات هي هياكل بيانات ثابتة الحجم تحتوي على عناصر من نفس النوع. تُعرَّف المصفوفة في Go بواسطة تحديد نوع البيانات الذي ستحتويه المصفوفة، وكذلك حجم المصفوفة. على عكس العديد من لغات البرمجة الأخرى، يتطلب Go أن يكون حجم المصفوفة ثابتًا عند تعريفها، ولا يمكن تغييره بعد ذلك.

تعريف المصفوفات

يتم تعريف المصفوفة في Go عن طريق تحديد الحجم والنوع، على سبيل المثال:

go
var arr [5]int

في المثال السابق، تم تعريف مصفوفة من نوع int تحتوي على 5 عناصر. بشكل افتراضي، يتم تهيئة العناصر بقيم صفرية من نوع البيانات المحدد (في هذه الحالة، 0 للأعداد الصحيحة).

يمكن أيضًا تعريف المصفوفات مع تهيئة القيم:

go
arr := [3]int{1, 2, 3}

في هذا المثال، تم تعريف مصفوفة تحتوي على 3 عناصر، وتم تهيئتها بالقيم 1 و 2 و 3.

خصائص المصفوفات

  1. ثبات الحجم: المصفوفات في Go ثابتة الحجم، بمعنى أنه بعد تعريف المصفوفة، لا يمكن تعديل حجمها. إذا أردت إضافة عناصر جديدة إلى المصفوفة أو تقليص عدد العناصر، فإنك بحاجة إلى إعادة تعريف مصفوفة جديدة.

  2. النوع الثابت: جميع عناصر المصفوفة يجب أن تكون من نفس النوع. على سبيل المثال، لا يمكنك إنشاء مصفوفة تحتوي على أعداد صحيحة ونصوص في نفس الوقت.

  3. التمرير بالمصفوفة: عند تمرير المصفوفة إلى دالة، يتم تمرير نسخة منها بشكل افتراضي (Pass by Value). هذا يعني أن أي تعديل على المصفوفة داخل الدالة لا يؤثر على المصفوفة الأصلية.

التكرار عبر المصفوفات

يمكنك التكرار عبر عناصر المصفوفة باستخدام حلقة for:

go
arr := [3]int{1, 2, 3} for i := 0; i < len(arr); i++ { fmt.Println(arr[i]) }

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

الشرائح (Slices) في لغة Go

الشرائح في Go هي نوع آخر من هياكل البيانات يُستخدم لتخزين مجموعات من البيانات، ولكنها أكثر مرونة من المصفوفات. على عكس المصفوفات، يمكن للشرائح أن تتغير في الحجم أثناء التنفيذ، مما يجعلها أكثر ملاءمة للاستخدام في العديد من الحالات التي تتطلب مرونة في التعامل مع البيانات.

تعريف الشرائح

يتم تعريف الشريحة باستخدام النوع []، ويمكن تهيئة الشريحة باستخدام مصفوفة أو مباشرة باستخدام القيم:

go
var slice []int

في هذا المثال، يتم تعريف شريحة من نوع int. هذه الشريحة تبدأ فارغة ولا تحتوي على أي عناصر.

يمكن أيضًا تهيئة الشريحة بالقيم بشكل مباشر:

go
slice := []int{1, 2, 3}

هنا، يتم تعريف شريحة تحتوي على 3 عناصر.

خصائص الشرائح

  1. المرونة في الحجم: على عكس المصفوفات، يمكن للشرائح تغيير حجمها بشكل ديناميكي. عندما تضيف عناصر جديدة إلى الشريحة، يتم تخصيص المزيد من الذاكرة لها، مما يتيح لك زيادة حجم الشريحة دون الحاجة إلى تعريفها من جديد.

  2. القدرة على التعديل: يمكن تعديل الشرائح في Go بحرية. عند تمرير الشريحة إلى دالة، يتم تمريرها بواسطة الإشارة (Pass by Reference)، مما يعني أن أي تعديل يحدث على الشريحة داخل الدالة سيؤثر على الشريحة الأصلية.

  3. التمثيل الداخلي: تعتبر الشريحة في Go تمثيلًا داخليًا للمصفوفات. كل شريحة تحتوي على ثلاثة عناصر: مؤشر العنصر الأول، الطول (عدد العناصر)، والسعة (العدد الأقصى للعناصر المخزنة قبل تخصيص المزيد من الذاكرة).

العمليات الشائعة على الشرائح

  • إضافة عناصر إلى الشريحة:

    يمكن استخدام دالة append لإضافة عناصر جديدة إلى الشريحة:

    go
    slice := []int{1, 2, 3} slice = append(slice, 4)

    في هذا المثال، يتم إضافة الرقم 4 إلى الشريحة.

  • القص (Slicing):

    إحدى القوى الكبرى للشرائح في Go هي القدرة على إنشاء شرائح جديدة من شرائح موجودة باستخدام عملية القص. على سبيل المثال:

    go
    slice := []int{1, 2, 3, 4, 5} newSlice := slice[1:4]

    في هذا المثال، الشريحة newSlice تحتوي على العناصر من الفهرس 1 إلى الفهرس 3 (الحد العلوي غير شامل).

التكرار عبر الشرائح

يمكنك أيضًا التكرار عبر العناصر في الشريحة باستخدام حلقة for:

go
slice := []int{1, 2, 3} for _, value := range slice { fmt.Println(value) }

في هذا المثال، يتم طباعة كل عنصر من عناصر الشريحة.

الفرق بين المصفوفات والشرائح في Go

على الرغم من أن كل من المصفوفات والشرائح تُستخدم لتخزين مجموعات من البيانات، إلا أن هناك العديد من الاختلافات بينهما:

  1. الحجم: المصفوفات ثابتة الحجم ولا يمكن تغييرها بعد تعريفها، بينما الشرائح ديناميكية الحجم ويمكن تعديلها خلال التنفيذ.

  2. المرونة: يمكن للشرائح أن تحتوي على حجم متغير ويمكن تعديلها بسهولة باستخدام دالة append، بينما المصفوفات لا تسمح بإضافة أو إزالة عناصر بعد إنشائها.

  3. التمرير إلى الدوال: عند تمرير المصفوفة إلى دالة، يتم تمرير نسخة منها (pass by value)، بينما عند تمرير الشريحة، يتم تمريرها بالإشارة (pass by reference).

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

التطبيقات العملية للمصفوفات والشرائح

  1. المصفوفات: غالبًا ما تُستخدم المصفوفات في الحالات التي يكون فيها حجم البيانات معروفًا مسبقًا، مثل تخزين مجموعة من القيم الثابتة أو تمثيل البيانات التي لا تحتاج إلى تعديل ديناميكي.

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

الخلاصة

في لغة Go، تعد المصفوفات والشرائح من الأدوات الأساسية التي يتم استخدامها بشكل متكرر. المصفوفات هي هياكل بيانات ثابتة الحجم، بينما الشرائح توفر مرونة أكبر من خلال السماح بتغيير حجم البيانات أثناء التنفيذ. كل من المصفوفات والشرائح لهما تطبيقات وأغراض خاصة بهما، ومن المهم اختيار النوع الأنسب بناءً على احتياجات البرنامج.