मुख्य सामग्री पर जाएं
मॉड्यूल 10 · पाठ 3 का 5पाठ्यक्रम में 48/50~15 min
मॉड्यूल पाठ (3/5)

जेनेरिक (गो 1.18+)

गो 1.18 (मार्च 2022) के बाद से, प्रकार पैरामीटर उपलब्ध हैं: कार्यों और प्रकारों को प्रकारों पर पैरामीटरयुक्त किया जा सकता है। वे आपको कोड डुप्लिकेट किए बिना और interface{} + रनटाइम प्रकार के दावे के बिना Map, Filter, Set[T], LinkedList[T] लिखने देते हैं।

सामान्य फ़ंक्शन: वाक्यविन्यास

Go
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 समानता की अनुमति देता है लेकिन नहीं < या >।

Go
func Index[T comparable](s []T, x T) int {
    for i, v := range s {
        if v == x { return i }
    }
    return -1
}

</> के लिए आपको एक कस्टम बाधा की आवश्यकता है।

कस्टम बाधा: प्रकार यूनियनें

एक बाधा "प्रकार तत्व" खंड के साथ एक इंटरफ़ेस है:

Go
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।

एक बाधा विधियों को मिश्रित कर सकती है और तत्वों को टाइप कर सकती है:

Go
type Stringable interface {
    ~string
    Len() int
}

सामान्य प्रकार

न केवल फ़ंक्शंस: स्ट्रक्चर्स और इंटरफ़ेस में टाइप पैरामीटर भी हो सकते हैं।

Go
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)।
  • आप पैरामीटराइज़िंग कर रहे हैं "क्योंकि आप कर सकते हैं": एक एकल उपयोग का मामला → इसका एक ठोस संस्करण बनाएं।

अभ्यास

व्यायाम#go.m10.l3.e1
प्रयास: 0लोड हो रहा है...

निश्चित रूप से जेनेरिक कार्य न्यूनतम [टी आदेश दिया गया] (ए, बी टी) टी चे रिटोर्ना इल माइनर यूसांडो एल'ऑपरेटर &lt;। इल बाधा आदेश दिया गया और फोरनिटो.

संपादक लोड हो रहा है...

3 प्रयासों के बाद समाधान उपलब्ध है

व्यायाम#go.m10.l3.e2
प्रयास: 0लोड हो रहा है...

कार्यान्वयन मानचित्र[टी, यू कोई भी](एस []टी, एफ फंक(टी) यू) []यू: एप्लिका एफ ए ओग्नी एलिमेंटो ई रेस्टिट्यूइस इल न्यूवो स्लाइस।

संपादक लोड हो रहा है...

3 प्रयासों के बाद समाधान उपलब्ध है

Quiz#go.m10.l3.e3
तैयार

अंतर्निहित सहमति से उत्पन्न होने वाली बाधा == यदि कोई ऑपरेटर नहीं है <?

Go
func Index[T ???](s []T, x T) int { ... }
उत्तर विकल्प