मैं एक * संरचना को एक * इंटरफ़ेस क्यों नहीं दे सकता?


142

मैं सिर्फ गो टूर के माध्यम से काम कर रहा हूं , और मैं संकेत और इंटरफेस के बारे में उलझन में हूं। यह गो कोड संकलन क्यों नहीं करता है?

package main

type Interface interface {}

type Struct struct {}

func main() {
    var ps *Struct
    var pi *Interface
    pi = ps

    _, _ = pi, ps
}

अगर Structएक है Interface, तो क्यों नहीं *Structहोगा एक *Interface?

मुझे मिलने वाला त्रुटि संदेश है:

prog.go:10: cannot use ps (type *Struct) as type *Interface in assignment:
        *Interface is pointer to interface, not interface

1
यह भी देखें stackoverflow.com/q/20874798/260805
Ztyx

ऐसा लगता है कि इंटरफेस अंतर्निहित संकेत की तरह व्यवहार कर सकता है ...
विक्टर

मैं के साथ अपने खेल का मैदान को बेहतर बनाने के सुझाव दे सकते हैं func main() { var ps *Struct = new(Struct) var pi *Interface var i Interface i = ps pi = &i fmt.Printf("%v, %v, %v\n", *ps, pi, &i) i = *ps fmt.Printf("%v, %v, %v\n", *ps, pi, i) _, _, _ = i, pi, ps }अपनी खुद की conclussions और बनाने
विक्टर

जवाबों:


183

जब आपके पास एक इंटरफ़ेस लागू करने वाली संरचना होती है, तो उस संरचना के लिए एक संकेतक स्वचालित रूप से उस इंटरफ़ेस को भी लागू करता है। यही कारण है कि आपके पास *SomeInterfaceफ़ंक्शंस के प्रोटोटाइप में कभी नहीं होता है, क्योंकि इससे कुछ भी नहीं जोड़ा जाएगा SomeInterface, और आपको इस तरह के वेरिएबल डिक्लेरेशन ( इस संबंधित प्रश्न देखें ) की आवश्यकता नहीं है।

एक अंतरफलक मूल्य ठोस संरचना का मूल्य नहीं है (क्योंकि इसका एक चर आकार है, यह संभव नहीं होगा), लेकिन यह एक प्रकार का सूचक है (संरचना के लिए अधिक सटीक संकेतक और प्रकार के लिए एक सूचक होना )। Russ कॉक्स इसका वर्णन बिल्कुल यहाँ करता है :

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

यहां छवि विवरण दर्ज करें

यही कारण है कि Interface, और न *Interfaceही एक संरचना को लागू करने के लिए एक संकेतक रखने के लिए सही प्रकार है Interface

तो आप बस का उपयोग करना चाहिए

var pi Interface

8
ठीक है, मुझे लगता है कि मेरे लिए समझ में आता है। मैं सोच रहा हूँ क्यों (उस मामले में), यह कहने के लिए बस एक संकलन समय त्रुटि नहीं है var pi *Interface
साइमन निकर्सन

1
मैं इसे समझाने के लिए और अधिक विवरणों में गया। संपादित देखें। मैं सुझाव देता हूं कि रस कॉक्स के लेख जिसे मैं लिंक करता हूं, को पढ़ना।
डेनस सेगुरेट

1
यह सिर्फ मुझे इस तरह से संकेत करने में मदद करता है कि मैं कभी भी C या C ++ में नहीं कर पाया था ... इस सुरुचिपूर्ण और सरल विवरण के लिए बहुत बहुत धन्यवाद :-)
mindplay.dk

2
ठीक है, मैं अभी भी नहीं मिलता है कि *SomeInterfaceबस एक संकलन त्रुटि क्यों नहीं है?
sazary

2
@charneykaye आप यहां पूरी तरह से सही नहीं हैं। इंटरफ़ेस चर घोषित करते समय या फ़ंक्शन घोषणा के भाग के रूप में इंटरफ़ेस प्रकार वापस करते समय आपके पास * SomeInterface कभी नहीं होता है । हालांकि आप एक समारोह के मापदंडों के भीतर * SomeInterface हो सकता है
arauter

7

शायद यही आपका मतलब है:

package main

type Interface interface{}

type Struct struct{}

func main() {
        var ps *Struct
        var pi *Interface
        pi = new(Interface)
        *pi = ps

        _, _ = pi, ps
}

संकलन ठीक है। यह भी देखें यहाँ


यह स्वीकार किया जाना चाहिए, अन्य वास्तव में सवाल का जवाब नहीं देता है।
DrKey


0

Im interface{}केवल eventsI interface{}तर्क के रूप में उपभोग करते हुए निम्नलिखित तरीके से im , अभी भी एक स्ट्रक्चर पॉइंटर्स भेजने में सक्षम है जैसा कि आप नीचे देख सकते हैं।

func Wait(seconds float64) *WaitEvent {
    return WaitEventCreate(seconds)
}

main.go

var introScene = []interface{}{
        storyboard.Wait(5),
        storyboard.Wait(2),
    }

    var storyboardI = storyboard.Create(stack, introScene)
    stack.Push(&storyboardI)

अब storyboard.goफाइल क्रिएट फंक्शन के अंदर

type Storyboard struct {
    Stack  *gui.StateStack
    Events []interface{} //always keep as last args
}

func Create(stack *gui.StateStack, eventsI interface{}) Storyboard {
    sb := Storyboard{
        Stack: stack,
    }

    if eventsI != nil {
        events := reflect.ValueOf(eventsI)
        if events.Len() > 0 {
            sb.Events = make([]interface{}, events.Len())
            for i := 0; i < events.Len(); i++ {
                sb.Events[i] = events.Index(i).Interface()
            }
        }
    }

    return sb
}

जैसा कि आप ऊपर देख सकते हैं Storyboard.go सिर्फ उपभोग कर रहा है Events []interface{}लेकिन वास्तव में Im भेजना एक स्ट्रक्चर पॉइंटर है और यह ठीक काम करता है।

यहाँ एक और उदाहरण

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.