أسئلة وأجوبة

كيف تنسخ الشرائح؟

الطرق

هناك عدة طرق لإنجاز المهمة.

الطريقة 1: استخدام make و copy


	cloned := make(SliceType, len(aSlice))
	copy(cloned, aSlice)

ملاحظة:

  • بدءاً من سلسلة أدوات Go v1.15، حُسّنت هذه الطريقة تحديداً بحيث لا تُصفَّر عناصر الشريحة المنسوخة في استدعاء make.
  • سعة الشريحة المنسوخة غير محاذية لحجم صنف ذاكرة (memory class size). (أحجام أصناف الذاكرة مذكورة في Go Optimizations 101.)

لهذين السببين، هذه الطريقة هي الأسرع.

عيوب هذه الطريقة:

  1. إذا كانت الشريحة المصدر aSlice تساوي nil، فإن الشريحة المنسوخة لا تساوي nil. أحياناً، يكون هذا مهماً.
  2. إنها مطوّلة قليلاً (تحتاج إلى سطرين).
  3. لا يمكن استخدامها كتعبير فرعي في الجمل.
  4. تحتاج إلى استيراد الحزمة الحاوية للنوع SliceType إذا كان SliceType معرّفاً في حزمة أخرى.

الطريقة 2: الصيغة الأكثر تطويلاً للطريقة 1


	var cloned SliceType
	if aSlice != nil {
		cloned = make(SliceType, len(aSlice))
		copy(cloned, aSlice)
	}

باستثناء العيب الأول للطريقة 1، تقدّم الصيغة المطوّلة فوائد وعيوباً مشابهة للطريقة 1.

الطريقة 3: استخدام make و append


	append(make(SliceType, 0, len(aSlice)), aSlice...)

يمكن استخدام هذه الطريقة كتعبير فرعي في الجمل.

ملاحظة:

عيوب هذه الطريقة:

  1. لهذين السببين، هذه الطريقة هي الأبطأ حالياً.
  2. إذا كانت الشريحة المصدر aSlice تساوي nil، فإن الشريحة المنسوخة لا تساوي nil. أحياناً، يكون هذا مهماً.
  3. تحتاج إلى استيراد الحزمة الحاوية للنوع SliceType إذا كان SliceType معرّفاً في حزمة أخرى.

الطريقة 4: استخدام append


	append(SliceType(nil), aSlice...) // الصيغة 1
	// أو
	append(SliceType{}, aSlice...) // الصيغة 2

على غرار الطريقة السابقة، يمكن استخدام هذه الطريقة كتعبير فرعي في الجمل.

ملاحظة:

  • هذه الطريقة لا تصفّر العناصر بلا داعٍ، لذا فهي ذات أداء جيد.
  • مع سلسلة الأدوات الرسمية، تكون سعة الشريحة المنسوخة محاذية لحجم صنف ذاكرة. هذا يجعلها ليست دائماً بسرعة الطريقة 1. (أحجام أصناف الذاكرة مذكورة في Go Optimizations 101.)

عيوب هذه الطريقة:

  1. لهذين السببين، هذه الطريقة أبطأ من غيرها. - في الصيغة 1، إذا كانت الشريحة المصدر aSlice شريحة فارغة غير nil، فإن الشريحة المنسوخة تكون nil.
  • في الصيغة 2، إذا كانت الشريحة المصدر aSlice شريحة nil، فإن الشريحة المنسوخة لا تكون nil.
  1. تحتاج إلى استيراد الحزمة الحاوية للنوع SliceType إذا كان SliceType معرّفاً في حزمة أخرى.

الطريقة 5: استخدام append ببراعة


	append(aSlice[:0:0], aSlice...)

تحسّن هذه الطريقة على السابقة بتجنّب العيبين المذكورين أعلاه، وهذا يعني:

  • إذا كانت الشريحة المصدر aSlice شريحة فارغة غير nil، فإن الشريحة المنسوخة أيضاً شريحة فارغة غير nil.
  • إذا كانت الشريحة المصدر aSlice شريحة nil، فإن الشريحة المنسوخة أيضاً nil.
  • لا تحتاج أبداً إلى استيراد الحزمة الحاوية للنوع SliceType.

قد يكون هذا أنظف تنفيذ مع الحفاظ على أداء ممتاز. إنه شبه مثالي. لكن له عيب واحد (صغير محتمل): إذا كانت الشريحة المصدر aSlice شريحة فارغة غير nil، فإن الشريحة المنسوخة (وهي أيضاً شريحة فارغة غير nil) تشير إلى كتلة ذاكرة العناصر الأساسية نفسها التي تشير إليها الشريحة المصدر. قد يمنع هذا (أو يؤخر) جمع كتلة ذاكرة العناصر عندما تصبح الشريحة المصدر غير مستخدمة.

يمكن إزالة هذا العيب الصغير عبر تحسين تنفيذ وقت التشغيل الرسمي لـ Go. لكن حتى الآن، لم يُجرَ التحسين.

الطريقة 6: استخدام slices.Clone (منذ Go 1.21)


import "slices"

	slices.Clone(aSlice)

التنفيذ الحالي لـ slices.Clone يستخدم ببساطة أسلوب الطريقة 5. لذا فهو يقدّم فوائد وعيوباً مشابهة للطريقة 5. وله عيب إضافي واحد: يحتاج إلى استيراد الحزمة القياسية "slices".

إذن؟

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