البرمجة الوظيفية في Go بمستوى متقدم

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

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

ابدأ الدورة

البرمجة الوظيفية في Go: المستوى المتقدم

\n\n

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

\n\n

1. الدوال النقية والثباتية

\n\n

الدالة النقية هي دالة:

\n
    \n
  • تعيد دائمًا نفس النتيجة لنفس الوسائط (الحتمية).
  • \n
  • ليس لها آثار جانبية (لا تغير الحالة الخارجية، ولا تكتب في ملفات/شبكة).
  • \n
\n\n

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

\n\n
package main\n\nimport "fmt"\n\n// دالة نقية: لا تغير الشريحة الأصلية، تعيد شريحة جديدة\nfunc DoubleSlice(s []int) []int {\n    result := make([]int, len(s))\n    for i, v := range s {\n        result[i] = v * 2\n    }\n    return result\n}\n\nfunc main() {\n    original := []int{1, 2, 3}\n    doubled := DoubleSlice(original)\n    fmt.Println(original) // [1 2 3] — بدون تغيير\n    fmt.Println(doubled)  // [2 4 6]\n}
\n\n

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

\n\n

2. الدوال عالية الترتيب والإغلاقات

\n\n

في Go، الدوال هي كائنات من الدرجة الأولى: يمكن تمريرها كوسائط، وإعادتها من دوال أخرى، وتخزينها في متغيرات. الإغلاق هو دالة تلتقط المتغيرات من النطاق الخارجي.

\n\n

مثال على دالة عالية الترتيب — Filter:

\n\n
package main\n\nimport "fmt"\n\n// Filter تعيد شريحة جديدة تحتوي على العناصر التي تحقق المسند\nfunc Filter[T any](s []T, predicate func(T) bool) []T {\n    var result []T\n    for _, v := range s {\n        if predicate(v) {\n            result = append(result, v)\n        }\n    }\n    return result\n}\n\nfunc main() {\n    numbers := []int{1, 2, 3, 4, 5, 6}\n    even := Filter(numbers, func(n int) bool { return n%2 == 0 })\n    fmt.Println(even) // [2 4 6]\n}
\n\n

تُستخدم الإغلاقات غالبًا لإنشاء مصانع دوال أو لتغليف الحالة:

\n\n
package main\n\nimport "fmt"\n\n// Counter تنشئ إغلاقًا يخزن حالة داخلية\nfunc Counter() func() int {\n    count := 0\n    return func() int {\n        count++\n        return count\n    }\n}\n\nfunc main() {\n    c1 := Counter()\n    fmt.Println(c1()) // 1\n    fmt.Println(c1()) // 2\n\n    c2 := Counter()\n    fmt.Println(c2()) // 1 — حالة مستقلة\n}
\n\n

3. تركيب الدوال والتطبيق الجزئي (الكاري)

\n\n

التركيب هو دمج عدة دوال في دالة واحدة جديدة. في Go، يتحقق التركيب من خلال دوال وسيطة. التطبيق الجزئي (الكاري) يسمح بتثبيت جزء من الوسائط وإعادة دالة تنتظر الباقي.

\n\n

مثال على التركيب:

\n\n
package main\n\nimport "fmt"\n\n// Compose تدمج دالتين: f(g(x))\nfunc Compose[A, B, C any](f func(B) C, g func(A) B) func(A) C {\n    return func(x A) C {\n        return f(g(x))\n    }\n}\n\nfunc addOne(x int) int { return x + 1 }\nfunc double(x int) int { return x * 2 }\n\nfunc main() {\n    addThenDouble := Compose(double, addOne)\n    fmt.Println(addThenDouble(3)) // (3+1)*2 = 8\n}
\n\n

الكاري على مثال دالة الجمع:

\n\n
package main\n\nimport "fmt"\n\n// Add — نسخة كاري من الجمع\nfunc Add(a int) func(int) int {\n    return func(b int) int {\n        return a + b\n    }\n}\n\nfunc main() {\n    addFive := Add(5)\n    fmt.                

المدونات

توصيات الكتب