मॉड्यूल पाठ (3/5)
जेनेरिक (गो 1.18+)
गो 1.18 (मार्च 2022) के बाद से, प्रकार पैरामीटर उपलब्ध हैं: कार्यों और प्रकारों को प्रकारों पर पैरामीटरयुक्त किया जा सकता है। वे आपको कोड डुप्लिकेट किए बिना और interface{} + रनटाइम प्रकार के दावे के बिना Map, Filter, Set[T], LinkedList[T] लिखने देते हैं।
सामान्य फ़ंक्शन: वाक्यविन्यास
func Map[T, U any](s []T, f func(T) U) []U {
out := make([]U, len(s))
for i, v := range s {
out[i] = f(v)
}
return out
}
doubled := Map([]int{1, 2, 3}, func(n int) int { return n * 2 })
// doubled is []int{2, 4, 6}तीन नए तत्व:
[T, U any]नाम के बाद: प्रकार पैरामीटर को उनकी बाधाओं के साथ घोषित करता है।any= बाधा जो किसी भी प्रकार को स्वीकार करती है (गो 1.18 के बाद सेinterface{}का उपनाम)।- अनुमान:
Map([]int{...}, ...)को कॉल करने पर आपकोMap[int, int](...)लिखने की आवश्यकता नहीं है: कंपाइलरT=int, U=intका अनुमान लगाता है।
कभी-कभी अनुमान पर्याप्त नहीं होता है (उदाहरण के लिए, बिना T तर्क वाले कंस्ट्रक्टर) और स्पष्ट तात्कालिकता की आवश्यकता होती है: New[*Server]()।
अंतर्निहित बाधाएँ
| बाधा | मतलब |
|---|---|
any | किसी भी प्रकार (== interface{}). |
comparable | == और != के साथ प्रकार: संख्यात्मक, स्ट्रिंग, बूल, पॉइंटर्स, चैनल, तुलनीय सरणी/संरचनाएं। |
comparable समानता की अनुमति देता है लेकिन नहीं < या >।
func Index[T comparable](s []T, x T) int {
for i, v := range s {
if v == x { return i }
}
return -1
}</> के लिए आपको एक कस्टम बाधा की आवश्यकता है।
कस्टम बाधा: प्रकार यूनियनें
एक बाधा "प्रकार तत्व" खंड के साथ एक इंटरफ़ेस है:
type Ordered interface {
~int | ~int64 | ~float64 | ~string
}
func Min[T Ordered](a, b T) T {
if a < b { return a }
return b
}|= यूनियन: किसी भी सूचीबद्ध प्रकार को स्वीकार करता है।~int= "int या किसी भी प्रकार कोtype X intके रूप में परिभाषित किया गया है" (समान अंतर्निहित प्रकार के साथ)।~के बिना, केवल सटीकint।
एक बाधा विधियों को मिश्रित कर सकती है और तत्वों को टाइप कर सकती है:
type Stringable interface {
~string
Len() int
}सामान्य प्रकार
न केवल फ़ंक्शंस: स्ट्रक्चर्स और इंटरफ़ेस में टाइप पैरामीटर भी हो सकते हैं।
type Set[T comparable] struct {
m map[T]struct{}
}
func NewSet[T comparable]() *Set[T] {
return &Set[T]{m: make(map[T]struct{})}
}
func (s *Set[T]) Add(v T) { s.m[v] = struct{}{} }
func (s *Set[T]) Has(v T) bool { _, ok := s.m[v]; return ok }
s := NewSet[string]()
s.Add("ada")विधियाँ प्रकार से परे प्रकार के पैरामीटर नहीं जोड़ सकतीं: func (s *Set[T]) MapTo[U any](...) संकलित नहीं होता (जानबूझकर डिजाइन सीमा)।
जेनरिक का उपयोग कब करें
हां जब:
- तर्क वास्तव में कई प्रकारों (संग्रह, एल्गोरिदम, सहायक जैसे
Map/Filter/Reduce) के लिए समान है। - विकल्प कोड की नकल करना या
interface{}+ प्रकार के दावे (प्रकार की सुरक्षा खोना) का उपयोग करना होगा।
नहीं कब:
- एक या दो तरीकों वाला इंटरफ़ेस पर्याप्त और अधिक पठनीय है (
io.Reader,fmt.Stringer)। - आप पैरामीटराइज़िंग कर रहे हैं "क्योंकि आप कर सकते हैं": एक एकल उपयोग का मामला → इसका एक ठोस संस्करण बनाएं।
अभ्यास
निश्चित रूप से जेनेरिक कार्य न्यूनतम [टी आदेश दिया गया] (ए, बी टी) टी चे रिटोर्ना इल माइनर यूसांडो एल'ऑपरेटर <। इल बाधा आदेश दिया गया और फोरनिटो.
3 प्रयासों के बाद समाधान उपलब्ध है
कार्यान्वयन मानचित्र[टी, यू कोई भी](एस []टी, एफ फंक(टी) यू) []यू: एप्लिका एफ ए ओग्नी एलिमेंटो ई रेस्टिट्यूइस इल न्यूवो स्लाइस।
3 प्रयासों के बाद समाधान उपलब्ध है
अंतर्निहित सहमति से उत्पन्न होने वाली बाधा == यदि कोई ऑपरेटर नहीं है <?
func Index[T ???](s []T, x T) int { ... }