الشرائح في Go مشابهة للقوائم أو المصفوفات في لغات أخرى. تحتوي على عدة عناصر من نوع محدد (أو واجهة).
الشرائح في Go مبنية على المصفوفات. المصفوفات لها حجم ثابت. أما الشريحة، فهي عرض مرن وحجمها ديناميكي لعناصر المصفوفة.
تُكتب الشريحة مثل []T حيث T هو نوع العناصر في الشريحة:
var empty []int // an empty slice
withData := []int{0,1,2,3,4,5} // a slice pre-filled with some data
يمكنك الحصول على عنصر عند فهرس معين يبدأ من الصفر أو تعيينه باستخدام ترميز الأقواس المربعة:
withData[1] = 5
x := withData[1] // x is now 5
يمكنك إنشاء شريحة جديدة من شريحة موجودة عبر أخذ نطاق من العناصر. مرة أخرى باستخدام ترميز الأقواس المربعة، لكن مع تحديد فهرس البداية (شامل) وفهرس النهاية (غير شامل). إذا لم تحدد فهرس البداية، فسيُفترض أنه 0. إذا لم تحدد فهرس النهاية، فسيُفترض أنه طول الشريحة.
newSlice := withData[2:4]
// => []int{2,3}
newSlice := withData[:2]
// => []int{0,1}
newSlice := withData[2:]
// => []int{2,3,4,5}
newSlice := withData[:]
// => []int{0,1,2,3,4,5}
يمكنك إضافة عناصر إلى شريحة باستخدام دالة append.
أدناه نضيف 4 و2 إلى الشريحة a.
a := []int{1, 3}
a = append(a, 4, 2)
// => []int{1,3,4,2}
تُرجع دالة append دائمًا شريحة جديدة، وعندما نريد فقط إضافة عناصر إلى شريحة موجودة، فمن الشائع إعادة إسنادها إلى متغير الشريحة الذي نمرره كأول وسيط كما فعلنا أعلاه.
يمكن أيضًا استخدام append لدمج شريحتين:
nextSlice := []int{100,101,102}
newSlice := append(withData, nextSlice...)
// => []int{0,1,2,3,4,5,100,101,102}
عادةً ما تقبل الدوال في Go عددًا ثابتًا فقط من الوسائط. ومع ذلك، من الممكن أيضًا كتابة دوال ذات عدد متغير من الوسائط في Go.
الدالة ذات العدد المتغير من الوسائط هي دالة تقبل عددًا متغيرًا من الوسائط.
إذا كان نوع المعامل الأخير في تعريف دالة مسبوقًا بعلامة القطع ...، فيمكن للدالة أن تقبل أي عدد من الوسائط لذلك المعامل.
func find(a int, b ...int) {
// ...
}
في الدالة أعلاه، المعامل b متغير ويمكننا تمرير 0 أو أكثر من الوسائط إلى b.
find(5, 6)
find(5, 6, 7)
find(5)
يجب أن يكون المعامل المتغير هو المعامل الأخير في الدالة.
تعمل الدوال ذات العدد المتغير من الوسائط عن طريق تحويل العدد المتغير من الوسائط إلى شريحة من نوع المعامل المتغير.
إليك مثالًا على تنفيذ دالة ذات عدد متغير من الوسائط.
func find(num int, nums ...int) {
fmt.Printf("type of nums is %T\n", nums)
for i, v := range nums {
if v == num {
fmt.Println(num, "found at index", i, "in", nums)
return
}
}
fmt.Println(num, "not found in ", nums)
}
func main() {
find(89, 90, 91, 95)
// =>
// type of nums is []int
// 89 not found in [90 91 95]
find(45, 56, 67, 45, 90, 109)
// =>
// type of nums is []int
// 45 found at index 2 in [56 67 45 90 109]
find(87)
// =>
// type of nums is []int
// 87 not found in []
}
في السطر find(89, 90, 91, 95) من البرنامج أعلاه، الوسائط المتغيرة العدد لدالة find هي 90 و91 و95.
تتوقع دالة find معاملًا متغيرًا من النوع int بعد num.
لذلك ستحوّل هذه الوسائط الثلاثة بواسطة المصرِّف إلى شريحة من النوع int هي []int{90, 91, 95} ثم ستُمرر إلى دالة find باسم nums.
أحيانًا تكون لديك شريحة بالفعل وتريد تمريرها إلى دالة ذات عدد متغير من الوسائط.
يمكن تحقيق ذلك بتمرير الشريحة متبوعة بـ ....
سيخبر ذلك المصرِّف باستخدام الشريحة كما هي داخل الدالة ذات العدد المتغير من الوسائط.
سيُحذف ببساطة في هذه الحالة الخطوة الموصوفة أعلاه حيث تُنشأ شريحة.
list := []int{1, 2, 3}
find(1, list...) // "find" defined as shown above
بصفتها ساحرةً ناشئة، تحتاج Elyse إلى التدرّب على بعض الأساسيات. لديها كومة من البطاقات تريد التعامل معها.
ولتسهيل الأمور قليلًا، تستخدم البطاقات من 1 إلى 10 فقط.
عند التدرّب على بطاقاتها، تحب Elyse أن تبدأ ببطاقاتها الثلاث المفضّلة من الرزمة: 2 و6 و9.
اكتب دالة FavoriteCards تُرجع شريحة تحتوي على هذه البطاقات بهذا الترتيب.
cards := FavoriteCards()
fmt.Println(cards)
// Output: [2 6 9]
أرجِع البطاقة الموجودة في الموضع index من الكومة المعطاة.
card := GetItem([]int{1, 2, 4, 1}, 2) // card == 4
إذا كان الفهرس خارج الحدود (أي إذا كان سالبًا أو بعد نهاية الكومة)، نريد أن نُرجع -1:
card := GetItem([]int{1, 2, 4, 1}, 10) // card == -1
بحسب العُرف في Go، يُرجع خطأ بدلًا من إرجاع قيمة "خارج الحدود".
هنا قيمة "خارج الحدود" هي -1 عندما يكون المتوقع عددًا صحيحًا موجبًا.
عند إرجاع خطأ، يُعد من الأسلوب المألوف إرجاع zero value مع الخطأ.
سيُغطّى إرجاع خطأ مع قيمة الإرجاع المناسبة في تمرين قادم.
استبدل البطاقة الموجودة في الموضع index بالبطاقة الجديدة المعطاة، وأرجِع الكومة المعدّلة.
لاحظ أن هذا سيعدّل شريحة الإدخال، وهو السلوك المتوقع.
index := 2
newCard := 6
cards := SetItem([]int{1, 2, 4, 1}, index, newCard)
fmt.Println(cards)
// Output: [1 2 6 1]
إذا كان الفهرس خارج الحدود (أي إذا كان سالبًا أو بعد نهاية الكومة)، نريد أن نضيف البطاقة الجديدة إلى نهاية الكومة:
index := -1
newCard := 6
cards := SetItem([]int{1, 2, 4, 1}, index, newCard)
fmt.Println(cards)
// Output: [1 2 4 1 6]
أضف البطاقة أو البطاقات المحددة في المعامل value إلى أعلى الكومة.
slice := []int{3, 2, 6, 4, 8}
cards := PrependItems(slice, 5, 1)
fmt.Println(cards)
// Output: [5 1 3 2 6 4 8]
إذا لم تُمرَّر أي وسيط للمعامل value، فستكون النتيجة مساوية للشريحة الأصلية.
slice := []int{3, 2, 6, 4, 8}
cards := PrependItems(slice)
fmt.Println(cards)
// Output: [3 2 6 4 8]
أزل البطاقة الموجودة في الموضع index من الكومة وأرجِع الكومة.
لاحظ أن هذا قد يعدّل شريحة الإدخال، ولا بأس بذلك.
cards := RemoveItem([]int{3, 2, 6, 4, 8}, 2)
fmt.Println(cards)
// Output: [3 2 4 8]
إذا كان الفهرس خارج الحدود (أي إذا كان سالبًا أو بعد نهاية الكومة)، نريد أن نترك الكومة دون تغيير:
cards := RemoveItem([]int{3, 2, 6, 4, 8}, 11)
fmt.Println(cards)
// Output: [3 2 6 4 8]
سجّل في Exercism لتتعلّم وتتقن Go عبر 34 مفهومًا165 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.