इंटरफ़ेस {} का अर्थ क्या है?


133

मैं इंटरफेस के लिए नया हूं और गितुब द्वारा सोप अनुरोध करने की कोशिश कर रहा हूं

मुझे इसका मतलब समझ नहीं आ रहा है

Msg interface{}

इस कोड में:

type Envelope struct {
    Body `xml:"soap:"`
}

type Body struct {
    Msg interface{}
}

मैं एक ही वाक्यविन्यास देखा है

fmt.Println

लेकिन समझ में नहीं आता कि इससे क्या हासिल हो रहा है

interface{}

20
interface{}void *सी। में कमोबेश बराबर है। यह किसी भी चीज़ की ओर इशारा कर सकता है और इसका उपयोग करने के लिए आपको एक कास्ट / टाइप अभिकथन की आवश्यकता होती है।
निक क्रेग-वुड

इंटरफ़ेस {} का अर्थ क्या है? Stackoverflow.com/a/62337836/12817546 देखें ।
टॉम जे

जवाबों:


189

आप लेख " गो में इंटरफेस का उपयोग कैसे करें " का संदर्भ ले सकते हैं (" रस कॉक्स इंटरफेस के विवरण " पर आधारित ):

इंटरफ़ेस क्या है ?

एक इंटरफ़ेस दो चीजें हैं:

  • यह विधियों का एक समूह है,
  • लेकिन यह भी एक प्रकार है

interface{}प्रकार, खाली इंटरफ़ेस इंटरफ़ेस कोई तरीकों किया है।

चूंकि कोई इम्प्लीमेंट कीवर्ड नहीं है, सभी प्रकार कम से कम शून्य विधियों को लागू करते हैं, और एक इंटरफ़ेस को संतुष्ट करना स्वचालित रूप से किया जाता है, सभी प्रकार खाली इंटरफ़ेस को संतुष्ट करते हैं
इसका मतलब है कि यदि आप एक फ़ंक्शन लिखते हैं जो interface{}एक पैरामीटर के रूप में एक मान लेता है , तो आप उस फ़ंक्शन को किसी भी मूल्य के साथ आपूर्ति कर सकते हैं

(यह वही है जो Msgआपके प्रश्न का प्रतिनिधित्व करता है: कोई भी मूल्य)

func DoSomething(v interface{}) {
   // ...
}

यहां यह भ्रमित करने वाला है:

DoSomethingफ़ंक्शन के अंदर , क्या vप्रकार है?

शुरुआत करने वाले गॉफ़र्स का मानना ​​है कि " vकिसी भी प्रकार का है", लेकिन यह गलत है।
vकिसी भी प्रकार का नहीं है; यह interface{}प्रकार का है

DoSomethingफ़ंक्शन में एक मान पास करते समय , गो रनटाइम एक प्रकार का रूपांतरण करेगा (यदि आवश्यक हो), और मूल्य को एक interface{}मूल्य में परिवर्तित कर सकता है
सभी मान रनटाइम पर बिल्कुल एक प्रकार के होते हैं, और vएक स्थिर प्रकार है interface{}

एक इंटरफ़ेस मान डेटा के दो शब्दों से निर्मित होता है :

  • एक शब्द का उपयोग मूल्य के अंतर्निहित प्रकार के लिए एक विधि तालिका को इंगित करने के लिए किया जाता है,
  • और दूसरे शब्द का उपयोग उस मान के वास्तविक डेटा को इंगित करने के लिए किया जाता है।

परिशिष्ट: यह है रस का लेख एक अंतरफलक संरचना के बारे में पूरा हो गया है:

type Stringer interface {
    String() string
}

इंटरफ़ेस मूल्यों को एक दो-शब्द जोड़ी के रूप में दर्शाया जाता है जो इंटरफ़ेस में संग्रहीत प्रकार और संबंधित डेटा के लिए एक संकेतक के बारे में एक संकेतक देता है।
स्ट्रिंग के इंटरफ़ेस मान को असाइन करना स्ट्रिंगर इंटरफ़ेस मूल्य के दोनों शब्दों को सेट करता है।

http://research.swtch.com/gointer2.png

इंटरफ़ेस वैल्यू में पहला शब्द उस बिंदु पर है जिसे मैं एक इंटरफ़ेस टेबल या इटेबल (स्पष्ट आई-टेबल; रनटाइम स्रोतों में, सी कार्यान्वयन नाम इताब) कहता हूं।
शामिल किए जाने वाले प्रकारों के बारे में कुछ मेटाडेटा के साथ itable शुरू होता है और फिर फ़ंक्शन पॉइंटर्स की एक सूची बन जाती है।
ध्यान दें कि itable इंटरफ़ेस प्रकार से मेल खाती है, न कि डायनेमिक प्रकार
हमारे उदाहरण के संदर्भ में, टाइपिंग Stringerबाइनरी को रखने के लिए उपयोग करने योग्य स्ट्रिंगर को संतुष्ट करने के लिए उपयोग किए जाने वाले तरीकों को सूचीबद्ध करता है, जो कि है String: बाइनरी के अन्य तरीके ( Get) में कोई उपस्थिति नहीं बनाते हैं itable

इंटरफ़ेस मूल्य में दूसरा शब्द वास्तविक डेटा पर इंगित करता है , इस मामले में की एक प्रति b
असाइनमेंट var s Stringer = bएक ही कारण के लिए bबिंदु की बजाय कॉपी बनाता है जो कॉपी बनाता है: यदि बाद में बदलता है,bvar c uint64 = bbs और cमाना जाता है कि मूल मूल्य है, नया नहीं।
इंटरफ़ेस में संग्रहीत मान मनमाने ढंग से बड़े हो सकते हैं, लेकिन केवल एक शब्द इंटरफ़ेस संरचना में मूल्य रखने के लिए समर्पित है, इसलिए असाइनमेंट ढेर पर मेमोरी का एक हिस्सा आवंटित करता है और एक-शब्द स्लॉट में सूचक को रिकॉर्ड करता है।


4
"डेटा के दो शब्द" से आपका क्या अभिप्राय है? विशेष रूप से, "शब्द" का क्या अर्थ है?
मिंगयू

3
@Mingyu मैंने उन दो शब्दों (32-बिट अंक) को चित्रित करने के लिए उत्तर पूरा कर लिया है।
वॉन

2
@Mingyu: VonC कंप्यूटर आर्किटेक्चर अर्थ में एक शब्द का उल्लेख कर रहा है - बिट्स का एक संग्रह जो डेटा के एक निश्चित आकार के टुकड़े को परिभाषित करता है। आपके द्वारा उपयोग किए जा रहे प्रोसेसर आर्किटेक्चर द्वारा शब्द का आकार नियंत्रित किया जाता है।
दान एसपारज़ा

1
धन्यवाद @VonC आपके उत्तर के लिए ... सच यह है कि मैं चीजों को पूछने पर डाउनपोस्ट पाने के लिए थक गया हूँ .. ज्यादातर लोग मुझे बताते हैं कि मुझे डॉक्स पढ़ना चाहिए ... अगर मुझे लगता है तो मैं आपके सुझाव को याद करूंगा ठीक से इसके लिए एक पोस्ट लिख सकते हैं ... लेकिन मैं वास्तव में पूछने के लिए दूसरे तरीके पर नहीं सोच सकता। वैसे भी धन्यवाद और मेरी कम इच्छा बहाना। इस पर एक नज़र डालने के लिए आपका स्वागत है: stackoverflow.com/questions/45577301/… यह स्पष्ट करने के लिए कि मुझे पूछना क्यों पसंद नहीं है।
विक्टर

1
@vic कोई समस्या नहीं है, और आपके पिछले खराब अनुभव के लिए क्षमा माँगता हूँ। यह सिर्फ इतना है कि टिप्पणियाँ सवाल और जवाब के लिए एक खराब फिट हैं।
VonC

34

interface{}इसका मतलब है कि आप अपने स्वयं के कस्टम प्रकार सहित किसी भी प्रकार का मूल्य रख सकते हैं। गो में सभी प्रकार एक खाली इंटरफ़ेस को संतुष्ट करते हैं ( interface{}एक खाली इंटरफ़ेस है)।
आपके उदाहरण में, Msg फ़ील्ड में किसी भी प्रकार का मान हो सकता है।

उदाहरण:

package main

import (
    "fmt"
)

type Body struct {
    Msg interface{}
}

func main() {
    b := Body{}
    b.Msg = "5"
    fmt.Printf("%#v %T \n", b.Msg, b.Msg) // Output: "5" string
    b.Msg = 5

    fmt.Printf("%#v %T", b.Msg, b.Msg) //Output:  5 int
}

खेल का मैदान जाओ


12

इसे खाली इंटरफ़ेस कहा जाता है और इसे सभी प्रकारों द्वारा कार्यान्वित किया जाता है, जिसका अर्थ है कि आप Msgक्षेत्र में कुछ भी रख सकते हैं ।

उदाहरण :

body := Body{3}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:3}

body = Body{"anything"}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:"anything"}

body = Body{body}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:main.Body{Msg:"anything"}}

यह इस तथ्य का तार्किक विस्तार है कि एक प्रकार एक इंटरफ़ेस को लागू करता है जैसे ही उसके पास इंटरफ़ेस के सभी तरीके हैं।


इसका मतलब यह है कि यह उपयोगकर्ता परिभाषित संरचना का एक उदाहरण हो सकता है ??
उपयोगकर्ता

11

यहां पहले से ही अच्छे उत्तर हैं। मुझे उन लोगों के लिए भी अपने खुद को जोड़ने दें जो इसे सहज रूप से समझना चाहते हैं:


इंटरफेस

यहाँ एक विधि के साथ एक इंटरफ़ेस है:

type Runner interface {
    Run()
}

तो किसी भी प्रकार की Run()विधि के लिए रनर इंटरफ़ेस को संतुष्ट करता है:

type Program struct {
    /* fields */
}

func (p Program) Run() {
    /* running */
}

func (p Program) Stop() {
    /* stopping */
}
  • हालाँकि प्रोग्राम प्रकार में एक स्टॉप विधि भी है, फिर भी यह रनर इंटरफ़ेस को संतुष्ट करता है क्योंकि इसकी आवश्यकता के लिए एक इंटरफ़ेस के सभी तरीकों को संतुष्ट करना है।

  • तो, यह एक रन विधि है और यह रनर इंटरफ़ेस को संतुष्ट करता है।


खाली इंटरफ़ेस

यहां किसी भी तरीके के बिना नामित इंटरफ़ेस है:

type Empty interface {
    /* it has no methods */
}

तो किसी भी प्रकार इस इंटरफ़ेस को संतुष्ट करता है। क्योंकि, इस इंटरफ़ेस को संतुष्ट करने के लिए किसी विधि की आवश्यकता नहीं है। उदाहरण के लिए:

// Because, Empty interface has no methods, following types satisfy the Empty interface
var a Empty

a = 5
a = 6.5
a = "hello"

लेकिन, क्या उपरोक्त प्रोग्राम प्रकार इसे संतुष्ट करता है? हाँ:

a = Program{} // ok

इंटरफ़ेस {} ऊपर के खाली इंटरफ़ेस के बराबर है।

var b interface{}

// true: a == b

b = a
b = 9
b = "bye"

जैसा कि आप देखते हैं, इसके बारे में कुछ भी रहस्यमय नहीं है लेकिन इसका दुरुपयोग करना बहुत आसान है। जितना हो सके इससे दूर रहें।


https://play.golang.org/p/A-vwTddWJ7G


type Runner interfaceजाओ खेल का मैदान उदाहरण में अप्रयुक्त है।
टॉम जे

9

से Golang निर्दिष्टीकरण :

एक इंटरफ़ेस प्रकार अपने इंटरफ़ेस नामक एक विधि सेट को निर्दिष्ट करता है। इंटरफ़ेस प्रकार का एक चर किसी भी प्रकार के मूल्य को एक विधि सेट के साथ संग्रहीत कर सकता है जो इंटरफ़ेस का कोई सुपरसेट है। इस प्रकार के इंटरफ़ेस को लागू करने के लिए कहा जाता है। इंटरफ़ेस प्रकार के एक uninitialized चर का मान शून्य है।

एक प्रकार किसी भी इंटरफ़ेस को लागू करता है जिसमें उसके तरीकों का कोई सबसेट शामिल होता है और इसलिए कई अलग-अलग इंटरफेस को लागू कर सकता है। उदाहरण के लिए, सभी प्रकार खाली इंटरफ़ेस लागू करते हैं:

इंटरफेस{}

अंगूर की अवधारणाएं हैं:

  1. सब कुछ एक प्रकार है । आप एक नए प्रकार परिभाषित कर सकते हैं, चलो अब यह फोन टी आइए मान लीजिए हमारे प्रकार T3 तरीकों है: A, B, C
  2. एक प्रकार के लिए निर्दिष्ट विधियों के सेट को " इंटरफ़ेस प्रकार " कहा जाता है " । चलो इसे हमारे उदाहरण में कहते हैं: T_interface। के बराबर हैT_interface = (A, B, C)
  3. आप विधियों के हस्ताक्षर को परिभाषित करके "इंटरफ़ेस प्रकार" बना सकते हैं ।MyInterface = (A, )
  4. जब आप एक निर्दिष्ट चर का प्रकार , "इंटरफ़ेस प्रकार", आप इसे करने के लिए जो एक अंतरफलक अपने इंटरफेस का सुपरसेट है कि केवल प्रकार प्रदान कर सकते हैं। इसका मतलब है कि निहित सभी तरीकों के MyInterfaceअंदर निहित होना चाहिएT_interface

आप यह मान सकते हैं कि सभी प्रकार के सभी "इंटरफ़ेस प्रकार" खाली इंटरफ़ेस का एक सुपरसेट हैं।


1

एक उदाहरण जो @VonC द्वारा उत्कृष्ट उत्तर और @ NickCraig-Wood द्वारा टिप्पणी का विस्तार करता है। interface{}कुछ भी इंगित कर सकते हैं और आपको इसका उपयोग करने के लिए एक कास्ट / टाइप अभिकथन की आवश्यकता है।

package main

import (
    . "fmt"
    "strconv"
)

var c = cat("Fish")
var d = dog("Bone")

func main() {
    var i interface{} = c
    switch i.(type) {
    case cat:
        c.Eat() // Fish
    }

    i = d
    switch i.(type) {
    case dog:
        d.Eat() // Bone
    }

    i = "4.3"
    Printf("%T %v\n", i, i) // string 4.3
    s, _ := i.(string)      // type assertion
    f, _ := strconv.ParseFloat(s, 64)
    n := int(f)             // type conversion
    Printf("%T %v\n", n, n) // int 4
}

type cat string
type dog string
func (c cat) Eat() { Println(c) }
func (d dog) Eat() { Println(d) }

iमान के साथ एक खाली इंटरफ़ेस का एक चर है cat("Fish")। इंटरफ़ेस प्रकार के मान से विधि मान बनाना कानूनी है। Https://golang.org/ref/spec#Interface_types देखें

एक प्रकार स्विच iइंटरफ़ेस प्रकार की पुष्टि करता है cat("Fish")Https://golang.org/doc/effective_go.html#type_switch देखें । iको फिर से सौंपा गया है dog("Bone")। एक प्रकार स्विच यह पुष्टि करता है कि iइंटरफ़ेस का प्रकार बदल गया हैdog("Bone")

आप संकलक को यह जांचने के लिए भी कह सकते हैं कि प्रकार असाइनमेंट का प्रयास करके Tइंटरफ़ेस Iको लागू करता है var _ I = T{}:। देखें https://golang.org/doc/faq#guarantee_satisfies_interface और https://stackoverflow.com/a/60663003/12817546

सभी प्रकार खाली इंटरफ़ेस को लागू करते हैं interface{}। देखें https://talks.golang.org/2012/goforc.slide#44 और https://golang.org/ref/spec#Interface_types । इस उदाहरण में, iपुन: असाइन किया गया है, इस बार एक स्ट्रिंग "4.3" पर। iफिर एक नया स्ट्रिंग चर के लिए असाइन किया गया है sके साथ i.(string)पहले sएक float64 प्रकार में बदल जाती है fका उपयोग कर strconv। अंत fमें n4. देखें के बराबर एक इंट प्रकार में परिवर्तित हो जाता है कि टाइप रूपांतरण और प्रकार के बीच का अंतर क्या है?

गो के बिल्ट-इन मैप्स और स्लाइस, साथ ही कंटेनरों के निर्माण के लिए खाली इंटरफ़ेस का उपयोग करने की क्षमता (स्पष्ट अनबॉक्सिंग के साथ) का अर्थ है कई मामलों में यह कोड लिखना संभव है कि क्या जेनरिक सक्षम होगा, अगर कम सुचारू रूप से। Https://golang.org/doc/faq#generics देखें ।


एक इंटरफ़ेस के साथ डिकूप कोड। Stackoverflow.com/a/62297796/12817546 देखें । एक विधि "गतिशील रूप से" कॉल करें। Stackoverflow.com/a/62336440/12817546 देखें । एक गो पैकेज पर पहुँचें। Stackoverflow.com/a/62278078/12817546 देखें । किसी वैरिएबल पर कोई मान निर्दिष्ट करें। Stackoverflow.com/a/62337836/12817546 देखें ।
टॉम जे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.