Contains في Go للمصفوفات: دليل شامل للمبتدئين

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

"أين دالة contains؟" — أول صدمة للمبتدئ في Go

\n\n

تخيل أنك تكتب كودًا بلغة Go، ولديك مصفوفة من النصوص ["python", "go", "rust", "javascript"]، وتريد التحقق مما إذا كانت تحتوي على اللغة "go". إذا كنت قادمًا من Python أو Ruby أو JavaScript، فستكتب تلقائيًا slice.contains("go") — وستصدم بخطأ أحمر في الترجمة. "ما هذا الهراء؟" — ستتساءل. "أي لغة محترمة لديها دالة contains للمجموعات!"

\n\n

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

\n\n

لماذا لا توجد دالة contains للمصفوفات في Go؟

\n

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

\n

علاوة على ذلك، دالة contains للمصفوفة هي دائمًا بحث خطي (O(n))، وإذا كنت تتوقع O(1)، فأنت تستخدم بنية بيانات خاطئة (تحتاج إلى map). Go لا يريد إخفاء هذا التعقيد.

\n\n

أبسط دالة contains لمصفوفة في Go (البحث اليدوي)

\n

لنكتب دالة contains لمصفوفة نصوص. هذا هو الكلاسيكي الذي ستراه في أي كود إنتاجي:

\n\n
package main\n\nimport "fmt"\n\n// Contains تتحقق من وجود عنصر في مصفوفة نصوص\nfunc Contains(slice []string, target string) bool {\n    for _, item := range slice {\n        if item == target {\n            return true\n        }\n    }\n    return false\n}\n\nfunc main() {\n    languages := []string{"python", "go", "rust", "javascript"}\n    fmt.Println(Contains(languages, "go"))       // true\n    fmt.Println(Contains(languages, "csharp"))   // false\n}
\n\n

الأمر بسيط: نمر على المصفوفة بحلقة، ونقارن كل عنصر بالعنصر المطلوب. إذا وجدناه — true، وإلا false. مهم: العامل == يعمل مع النصوص، الأرقام، القيم المنطقية، والمؤشرات. لا يعمل مع الهياكل أو المصفوفات المتداخلة.

\n\n

دالة contains للأرقام

\n

لمصفوفة الأعداد الصحيحة، الكود مشابه جدًا:

\n\n
func ContainsInt(slice []int, target int) bool {\n    for _, v := range slice {\n        if v == target {\n            return true\n        }\n    }\n    return false\n}\n\nfunc main() {\n    numbers := []int{10, 20, 30, 40, 50}\n    fmt.Println(ContainsInt(numbers, 30)) // true\n    fmt.Println(ContainsInt(numbers, 99)) // false\n}
\n\n

غير مريح؟ نعم. لكن هذه هي Go — الوضوح والبساطة فوق كل شيء.

\n\n

دالة contains عامة لمصفوفة في Go (الأدوية، Go 1.18+)

\n

مع إصدار Go 1.18، ظهرت الأدوية (Generics). الآن يمكنك كتابة دالة contains واحدة لأي نوع يدعم المقارنة:

\n\n
package main\n\nimport "fmt"\n\n// ContainsGeneric تعمل مع أي نوع comparable\nfunc ContainsGeneric[T comparable](slice []T, target T) bool {\n    for _, item := range slice {\n        if item == target {\n            return true\n        }\n    }\n    return false\n}\n\nfunc main() {\n    strs := []string{"a", "b", "c"}\n    ints := []int{1, 2, 3}\n    floats := []float64{1.1, 2.2, 3.3}\n\n    fmt.Println(ContainsGeneric(strs, "b"))   // true\n    fmt.Println(ContainsGeneric(ints, 5))     // false\n    fmt.Println(ContainsGeneric(floats, 2.2)) // true\n}
\n\n

القيود comparable تعني أن النوع يدعم العوامل == و

المدونات

توصيات الكتب