الطرق
هناك عدة طرق لإنجاز المهمة.
الطريقة 1: استخدام make و copy
cloned := make(SliceType, len(aSlice))
copy(cloned, aSlice)
ملاحظة:
- بدءاً من سلسلة أدوات Go v1.15، حُسّنت هذه الطريقة تحديداً بحيث لا تُصفَّر عناصر الشريحة المنسوخة في استدعاء
make. - سعة الشريحة المنسوخة غير محاذية لحجم صنف ذاكرة (memory class size). (أحجام أصناف الذاكرة مذكورة في Go Optimizations 101.)
لهذين السببين، هذه الطريقة هي الأسرع.
عيوب هذه الطريقة:
- إذا كانت الشريحة المصدر
aSliceتساوي nil، فإن الشريحة المنسوخة لا تساوي nil. أحياناً، يكون هذا مهماً. - إنها مطوّلة قليلاً (تحتاج إلى سطرين).
- لا يمكن استخدامها كتعبير فرعي في الجمل.
- تحتاج إلى استيراد الحزمة الحاوية للنوع
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...)
يمكن استخدام هذه الطريقة كتعبير فرعي في الجمل.
ملاحظة:
- سيصفّر استدعاء
makeعناصر الشريحة المنسوخة بلا داعٍ، - مع سلسلة الأدوات الرسمية، تكون سعة الشريحة المنسوخة محاذية لحجم صنف ذاكرة. قد يجعلها هذا حتى أبطأ. (أحجام أصناف الذاكرة مذكورة في Go Optimizations 101.)
عيوب هذه الطريقة:
- لهذين السببين، هذه الطريقة هي الأبطأ حالياً.
- إذا كانت الشريحة المصدر
aSliceتساوي nil، فإن الشريحة المنسوخة لا تساوي nil. أحياناً، يكون هذا مهماً. - تحتاج إلى استيراد الحزمة الحاوية للنوع
SliceTypeإذا كانSliceTypeمعرّفاً في حزمة أخرى.
الطريقة 4: استخدام append
append(SliceType(nil), aSlice...) // الصيغة 1
// أو
append(SliceType{}, aSlice...) // الصيغة 2
على غرار الطريقة السابقة، يمكن استخدام هذه الطريقة كتعبير فرعي في الجمل.
ملاحظة:
- هذه الطريقة لا تصفّر العناصر بلا داعٍ، لذا فهي ذات أداء جيد.
- مع سلسلة الأدوات الرسمية، تكون سعة الشريحة المنسوخة محاذية لحجم صنف ذاكرة. هذا يجعلها ليست دائماً بسرعة الطريقة 1. (أحجام أصناف الذاكرة مذكورة في Go Optimizations 101.)
عيوب هذه الطريقة:
- لهذين السببين، هذه الطريقة أبطأ من غيرها. - في الصيغة 1، إذا كانت الشريحة المصدر
aSliceشريحة فارغة غير nil، فإن الشريحة المنسوخة تكون nil.
- في الصيغة 2، إذا كانت الشريحة المصدر
aSliceشريحة nil، فإن الشريحة المنسوخة لا تكون nil.
- تحتاج إلى استيراد الحزمة الحاوية للنوع
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. اختر فقط الطريقة التي تناسب حالتك أفضل.