यह सब Go 1.18 से शुरू हुआ: जेनेरिक्स सिर्फ एक फैशनेबल फीचर क्यों नहीं है?
\n\nलंबे समय तक, Go समुदाय को भाषा की सरलता पर गर्व था। सामान्यीकृत प्रोग्रामिंग (generics) की अनुपस्थिति को एक सचेत विकल्प माना जाता था: "हमें जटिल टेम्पलेट की आवश्यकता नहीं है, हम समझने योग्य कोड लिखते हैं"। लेकिन वास्तविकता ने अपना असर दिखाया। डेवलपर्स int, string और float64 के लिए फंक्शन कॉपी-पेस्ट करते-करते थक गए थे — या interface{} का उपयोग करके टाइप कास्टिंग करते थे, जिससे कंपाइलेशन के समय सुरक्षा खत्म हो जाती थी।
Go 1.18 (2022) का आगमन एक क्रांति थी। जेनेरिक्स (generics) ने भाषा में टाइप पैरामीटर (type parameters) और प्रतिबंध (constraints) जोड़े। अब Go प्रोग्रामर प्रदर्शन और सख्त टाइपिंग से समझौता किए बिना सामान्यीकृत डेटा संरचनाएं और एल्गोरिदम लिख सकते हैं।
\n\nइस लेख में pythonlib.ru पर, हम समझेंगे कि Go में generics कैसे काम करते हैं, वास्तविक कोड उदाहरण देखेंगे और जानेंगे कि उनका उपयोग कब करना चाहिए और कब नहीं। चलिए शुरू करते हैं!
\n\nसरल शब्दों में Go में generics क्या है?
\n\nकल्पना करें कि आप एक फंक्शन लिख रहे हैं जो एक स्लाइस में न्यूनतम तत्व ढूंढता है। जेनेरिक्स के बिना, आपको तीन संस्करण बनाने होंगे: int, float64 और string के लिए। या interface{} का उपयोग करके टाइप कास्टिंग करनी होगी — धीमी और असुरक्षित।
Generics आपको एक फंक्शन लिखने की अनुमति देता है जो किसी भी प्रकार के साथ काम करता है, बशर्ते वह कुछ शर्तों को पूरा करता हो। सिंटैक्स सरल है: फंक्शन के नाम के बाद वर्गाकार कोष्ठक में टाइप पैरामीटर निर्दिष्ट किए जाते हैं।
\n\nसिंटैक्स: वर्गाकार कोष्ठक और शब्द any
\n\npackage main\n\nimport "fmt"\n\n// Min — न्यूनतम खोजने के लिए सामान्यीकृत फंक्शन\nfunc Min[T any](a, b T) T {\n // त्रुटि: any के लिए < ऑपरेटर परिभाषित नहीं है\n // if a < b {\n // return a\n // }\n return b\n}\n\nउपरोक्त कोड संकलित नहीं होगा क्योंकि any एक खाली इंटरफ़ेस है (interface{} का पर्याय)। कंपाइलर नहीं जानता कि क्या प्रकार < ऑपरेटर का समर्थन करता है। प्रतिबंध (constraint) जोड़ने की आवश्यकता है।
टाइप प्रतिबंध: constraints
\n\nGo में, प्रतिबंध इंटरफ़ेस के माध्यम से निर्दिष्ट किए जाते हैं। आप पैकेज golang.org/x/exp/constraints से अंतर्निहित प्रतिबंधों का उपयोग कर सकते हैं या अपने स्वयं के लिख सकते हैं।
import (\n "fmt"\n "golang.org/x/exp/constraints"\n)\n\n// Min किसी भी क्रमबद्ध प्रकार के साथ काम करता है\nfunc Min[T constraints.Ordered](a, b T) T {\n if a < b {\n return a\n }\n return b\n}\n\nfunc main() {\n fmt.Println(Min(10, 20)) // 10\n fmt.Println(Min(3.14, 2.71)) // 2.71\n fmt.Println(Min("apple", "banana")) // "apple"\n}\n\nध्यान दें: constraints.Ordered में वे सभी प्रकार शामिल हैं जिनके लिए ऑपरेटर <, <=, >, >= परिभाषित हैं — ये int, float, string हैं।
व्यावहारिक उदाहरण: सरल से जटिल तक
\n\nआइए देखें कि Go में generics वास्तविक कोड लिखने को कैसे सरल बनाते हैं।
\n\n1. सामान्यीकृत स्टैक (Stack)
\n\nजेनेरिक्स के बिना, आपको []interface{} स्टोर करना होगा और type assertion करना होगा। Generics के साथ — सुरुचिपूर्ण और सुरक्षित।
package main\n\nimport "fmt"\n\n// Stack — सामान्यीकृत डेटा संरचना\ntype Stack[T any] struct {\n items []T\n}\n\nfunc (s *Stack[T]) Push(item T) {\n s.items = append(s.items, item)\n}\n\nfunc (s *Stack[T]) Pop() (T, bool) {\n if len(s.items) == 0 {\n var zero T\n return zero, false\n }\n item := s.items[len(s.items)-1]\n s.items = s.items[:len(s.items)-1]\n return item, true\n}\n\nfunc main() {\n intStack := Stack[int]{}\n intStack.Push(1)\n intStack.Push(2)\n val, ok := intStack.Pop()\n fmt.Println(val, ok) // 2 true\n\n strStack := Stack[string]{}\n strStack.Push("hello")\n