यह संकलन-समय त्रुटि तब उत्पन्न होती है जब आप इंटरफ़ेस प्रकार के लिए एक ठोस प्रकार को असाइन या पास (या परिवर्तित) करने का प्रयास करते हैं ; और प्रकार ही इंटरफ़ेस को लागू नहीं करता है, केवल एक सूचक प्रकार के लिए ।
आइए एक उदाहरण देखें:
type Stringer interface {
String() string
}
type MyType struct {
value string
}
func (m *MyType) String() string { return m.value }
Stringer
इंटरफ़ेस प्रकार केवल एक विधि है: String()
। इंटरफ़ेस मान में संग्रहीत किसी भी मान में Stringer
यह विधि होनी चाहिए। हमने एक भी बनाया MyType
, और हमने पॉइंटर रिसीवर के MyType.String()
साथ एक विधि बनाई । इसका मतलब यह है कि विधि प्रकार के विधि सेट में है , लेकिन इसमें नहीं है ।String()
*MyType
MyType
जब हम MyType
किसी वैरिएबल के प्रकार का मान निर्दिष्ट करने का प्रयास करते हैं Stringer
, तो हमें प्रश्न में त्रुटि मिलती है:
m := MyType{value: "something"}
var s Stringer
s = m // cannot use m (type MyType) as type Stringer in assignment:
// MyType does not implement Stringer (String method has pointer receiver)
लेकिन सब कुछ ठीक है अगर हम टाइप *MyType
करने के लिए एक मान निर्दिष्ट करने की कोशिश करते हैं Stringer
:
s = &m
fmt.Println(s)
और हम अपेक्षित परिणाम प्राप्त करते हैं (इसे खेल के मैदान पर आज़माएं ):
something
तो इस संकलन-समय त्रुटि प्राप्त करने के लिए आवश्यकताओं:
- गैर-पॉइंटर कंक्रीट प्रकार का एक मूल्य सौंपा जा रहा है (या पारित या परिवर्तित)
- एक इंटरफ़ेस प्रकार जिसे सौंपा जा रहा है (या उसे पास या परिवर्तित किया गया है)
- कंक्रीट प्रकार में इंटरफ़ेस की आवश्यक विधि है, लेकिन एक पॉइंटर रिसीवर के साथ
समस्या को हल करने के लिए संभावनाएँ:
- मूल्य के लिए एक संकेतक का उपयोग किया जाना चाहिए, जिसकी विधि सेट में सूचक रिसीवर के साथ विधि शामिल होगी
- या रिसीवर प्रकार को गैर-पॉइंटर में बदलना होगा , इसलिए गैर-पॉइंटर कंक्रीट प्रकार के सेट में विधि भी शामिल होगी (और इस प्रकार इंटरफ़ेस को संतुष्ट करें)। यह व्यवहार्य हो सकता है या नहीं भी हो सकता है, क्योंकि यदि विधि को मूल्य को संशोधित करना है, तो एक गैर-पॉइंटर रिसीवर एक विकल्प नहीं है।
संरचनाएं और एम्बेडिंग
संरचना और एम्बेडिंग का उपयोग करते समय , अक्सर यह "आप" नहीं होता है जो एक इंटरफ़ेस लागू करता है (एक विधि कार्यान्वयन प्रदान करता है), लेकिन एक प्रकार जिसे आप अपने में एम्बेड करते हैं struct
। इस उदाहरण में पसंद करें:
type MyType2 struct {
MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: m}
var s Stringer
s = m2 // Compile-time error again
फिर से, संकलन-समय त्रुटि, क्योंकि विधि के सेट में एम्बेडेड MyType2
की String()
विधि नहीं होती है MyType
, केवल विधि सेट की जाती है *MyType2
, इसलिए निम्न कार्य करता है (इसे Go Playground पर आज़माएं ):
var s Stringer
s = &m2
हम इसे काम भी कर सकते हैं, अगर हम *MyType
केवल एक गैर-पॉइंटर को एम्बेड और उपयोग करते हैं MyType2
(इसे गो प्लेग्राउंड पर आज़माएं ):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = m2
इसके अलावा, जो कुछ भी हम एम्बेड (या तो MyType
या *MyType
), अगर हम एक सूचक का उपयोग *MyType2
, यह होगा हमेशा काम (इस पर कोशिश जाओ खेल का मैदान ):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = &m2
युक्ति से प्रासंगिक खंड (अनुभाग संरचना प्रकार से ):
एक संरचनात्मक प्रकार S
और एक प्रकार का नाम T
दिया गया है , पदोन्नत तरीकों को संरचना के सेट में निम्नानुसार शामिल किया गया है:
- यदि
S
एक गुमनाम फ़ील्ड है T
, की विधि सेट S
और *S
दोनों पदोन्नत रिसीवर के साथ तरीकों में शामिल हैं T
। *S
रिसीवर के साथ प्रोमोटेड विधियों में सेट विधि भी शामिल है *T
।
- यदि
S
एक गुमनाम फ़ील्ड है *T
, की विधि सेट S
और *S
दोनों पदोन्नत रिसीवर के साथ तरीकों में शामिल हैं T
या *T
।
तो दूसरे शब्दों में: यदि हम एक गैर-पॉइंटर प्रकार को एम्बेड करते हैं, तो नॉन-पॉइंटर एंबेडर की विधि सेट केवल गैर-पॉइंटर रिसीवर (एम्बेडेड प्रकार से) के साथ विधियां प्राप्त करती है।
यदि हम एक पॉइंटर प्रकार को एम्बेड करते हैं, तो नॉन-पॉइंटर एंबेडर की विधि सेट को पॉइंटर और नॉन-पॉइंटर रिसीवर्स (एम्बेडेड प्रकार से) दोनों के तरीके मिलते हैं।
यदि हम एंबेडर के लिए एक पॉइंटर मान का उपयोग करते हैं, तो इसकी परवाह किए बिना कि एंबेडेड प्रकार पॉइंटर है या नहीं, एंबेडर को पॉइंटर के सेट को हमेशा पॉइंटर और नॉन-पॉइंटर रिसीवर्स (एम्बेडेड प्रकार से) दोनों के तरीके मिलते हैं।
ध्यान दें:
वहाँ आप एक इंटरफेस मूल्य जिनमें से एक मूल्य लपेटता है अर्थात् जब एक बहुत ही इसी तरह की स्थिति है, MyType
है, और आप करने की कोशिश ज़ोर टाइप , यह से दूसरे इंटरफेस मूल्य Stringer
। इस मामले में, ऊपर वर्णित कारणों के लिए जोर नहीं होगा, लेकिन हमें थोड़ा अलग रनटाइम त्रुटि मिलती है:
m := MyType{value: "something"}
var i interface{} = m
fmt.Println(i.(Stringer))
रनटाइम घबराहट (इसे खेल के मैदान पर आज़माएं ):
panic: interface conversion: main.MyType is not main.Stringer:
missing method String
टाइप एस्टर के बजाय बदलने की कोशिश कर रहे हैं, हम संकलन-समय त्रुटि प्राप्त कर रहे हैं:
m := MyType{value: "something"}
fmt.Println(Stringer(m))
func (m *MyType)
", या कोई भी नहीं । ऐसा है क्या? क्या मैं "सदस्य फ़ंक्शंस",func (m *MyType)
औरfunc (m MyType)
?