Go में कार्यात्मक प्रोग्रामिंग: A से Z तक
\n\nGo (Golang) एक ऐसी भाषा है जिसे अक्सर अनिवार्य और समवर्ती प्रोग्रामिंग से जोड़ा जाता है। हालाँकि, इसकी लचीली प्रकार प्रणाली और प्रथम श्रेणी के फ़ंक्शन कार्यात्मक शैली को सफलतापूर्वक लागू करने की अनुमति देते हैं। इस लेख में, हम Go में कार्यात्मक प्रोग्रामिंग (FP) का उपयोग करने का तरीका समझेंगे: बुनियादी अवधारणाओं से लेकर व्यावहारिक उदाहरणों तक। आप सीखेंगे कि कैसे अधिक स्वच्छ, पूर्वानुमानित और परीक्षण योग्य कोड लिखें।
\n\nGo के संदर्भ में कार्यात्मक प्रोग्रामिंग क्या है?
\n\nकार्यात्मक प्रोग्रामिंग एक प्रतिमान है जहाँ गणनाएँ फ़ंक्शन के अनुप्रयोग पर आधारित होती हैं, जिसमें स्थिति में परिवर्तन और दुष्प्रभावों से बचा जाता है। Go में, यह इस प्रकार व्यक्त किया जाता है:
\n- \n
- शुद्ध फ़ंक्शन — परिणाम केवल तर्कों पर निर्भर करता है, बाहरी डेटा में कोई उत्परिवर्तन नहीं। \n
- उच्च-क्रम फ़ंक्शन — फ़ंक्शन जो अन्य फ़ंक्शन को तर्क के रूप में लेते हैं या उन्हें लौटाते हैं। \n
- क्लोज़र — अनाम फ़ंक्शन जो बाहरी दायरे से चर को "याद" रखते हैं। \n
- डेटा अपरिवर्तनीयता — बदलने के बजाय कॉपी करने को प्राथमिकता। \n
हालाँकि Go पूरी तरह से कार्यात्मक भाषा नहीं है (इसमें मोनाड या बीजगणितीय डेटा प्रकार नहीं हैं), यह FP दृष्टिकोणों के प्रभावी उपयोग के लिए पर्याप्त उपकरण प्रदान करता है।
\n\nअनाम फ़ंक्शन और क्लोज़र
\n\nGo में, फ़ंक्शन प्रथम श्रेणी की वस्तुएँ हैं। उन्हें चरों को सौंपा जा सकता है, अन्य फ़ंक्शन में पास किया जा सकता है और लौटाया जा सकता है। अनाम फ़ंक्शन (लैम्ब्डा) कार्यात्मक शैली का आधार हैं।
\n\nअनाम फ़ंक्शन का उदाहरण
\npackage main\n\nimport "fmt"\n\nfunc main() {\n // एक चर को सौंपा गया अनाम फ़ंक्शन\n multiply := func(x, y int) int {\n return x * y\n }\n\n result := multiply(5, 3)\n fmt.Println(result) // 15\n}\n\nक्लोज़र (Closures)
\nक्लोज़र एक अनाम फ़ंक्शन है जो बाहरी दायरे से चर को "कैप्चर" करता है। यह जनरेटर और स्थिति वाले फ़ंक्शन बनाने के लिए एक शक्तिशाली उपकरण है।
\n\npackage main\n\nimport "fmt"\n\n// अनुक्रम जनरेटर\nfunc sequence() func() int {\n i := 0\n return func() int {\n i++\n return i\n }\n}\n\nfunc main() {\n next := sequence()\n fmt.Println(next()) // 1\n fmt.Println(next()) // 2\n fmt.Println(next()) // 3\n\n // sequence() का प्रत्येक कॉल एक नया क्लोज़र बनाता है\n next2 := sequence()\n fmt.Println(next2()) // 1\n}\n\nक्लोज़र वैश्विक चर का उपयोग किए बिना स्थिति को एनकैप्सुलेट करने के लिए आदर्श हैं — यह Go में कार्यात्मक दृष्टिकोण का आधार है।
\n\nशुद्ध फ़ंक्शन और अपरिवर्तनीयता
\n\nशुद्ध फ़ंक्शन का कोई दुष्प्रभाव नहीं होता और यह पास किए गए डेटा को नहीं बदलता। Go में, इसके लिए सचेत दृष्टिकोण की आवश्यकता होती है, क्योंकि स्लाइस और मैप संदर्भ द्वारा पास किए जाते हैं।
\n\nशुद्ध फ़ंक्शन का उदाहरण (बिना उत्परिवर्तन के)
\npackage main\n\nimport "fmt"\n\n// शुद्ध फ़ंक्शन: मूल स्लाइस को नहीं बदलता\nfunc doubleValues(input []int) []int {\n result := make([]int, len(input))\n for i, v := range input {\n result[i] = v * 2\n }\n return result\n}\n\nfunc main() {\n original := []int{1, 2, 3, 4}\n doubled := doubleValues(original)\n\n fmt.Println("Original:", original) // [1 2 3 4]\n fmt.Println("Doubled:", doubled) // [2 4 6 8]\n}\n\nध्यान दें: हम मूल को बदलने के बजाय एक नया स्लाइस बनाते हैं। यह अपरिवर्तनीयता (immutability) सुनिश्चित करता है — FP का एक प्रमुख सिद्धांत।
\n\nउच्च-क्रम फ़ंक्शन: map, filter, reduce
\nहालाँकि Go में स्लाइस के लिए अंतर्निहित map/filter/reduce विधियाँ नहीं हैं, उन्हें आसानी से स्वयं लागू किया जा सकता है।
\n\npackage main\n\nimport "fmt"\n\n// Map — प्रत्येक तत्व पर फ़ंक्शन लागू करता है\nfunc Map[T any](items []T, fn func(T) T) []T {\n result := make([]T, len(items))\n for