स्ट्रिंग टाइप करने के लिए डेटा (टाइप इंटरफ़ेस {}) को रूपांतरित नहीं कर सकते हैं: टाइप एश्योरेंस की आवश्यकता है


178

मैं जाने के लिए बहुत नया हूं और मैं इस अधिसूचित पैकेज के साथ खेल रहा था ।

पहले मेरे पास कोड था जो इस तरह दिखता था:

func doit(w http.ResponseWriter, r *http.Request) {
    notify.Post("my_event", "Hello World!")
    fmt.Fprint(w, "+OK")
}

मैं न्यूलाइन को अपेंड करना चाहता था, Hello World!लेकिन doitऊपर के फंक्शन में नहीं , क्योंकि यह बहुत ही मामूली होगा, लेकिन handlerइसके बाद के संस्करण में नीचे इस प्रकार है:

func handler(w http.ResponseWriter, r *http.Request) {
    myEventChan := make(chan interface{})
    notify.Start("my_event", myEventChan)
    data := <-myEventChan
    fmt.Fprint(w, data + "\n")
}

के बाद go run:

$ go run lp.go 
# command-line-arguments
./lp.go:15: invalid operation: data + "\n" (mismatched types interface {} and string)

थोड़ा सा Googling के बाद मुझे SO पर यह सवाल मिला ।

फिर मैंने अपना कोड अपडेट किया:

func handler(w http.ResponseWriter, r *http.Request) {
    myEventChan := make(chan interface{})
    notify.Start("my_event", myEventChan)
    data := <-myEventChan
    s:= data.(string) + "\n"
    fmt.Fprint(w, s)
}

क्या यह मुझे करना चाहिए था? मेरी संकलक त्रुटियां दूर हो गई हैं इसलिए मुझे लगता है कि यह बहुत अच्छा है? क्या यह कुशल है? क्या आपको इसे अलग तरह से करना चाहिए?

जवाबों:


292

गो विनिर्देशन के अनुसार :

इंटरफ़ेस प्रकार और एक्स प्रकार की अभिव्यक्ति एक्स के लिए, प्राथमिक अभिव्यक्ति एक्स (टी) का दावा है कि एक्स शून्य नहीं है और एक्स में संग्रहित मूल्य टाइप टी का है।

एक "टाइप अभिकथन" आपको एक इंटरफ़ेस मूल्य घोषित करने की अनुमति देता है जिसमें एक निश्चित ठोस प्रकार होता है या इसका ठोस प्रकार दूसरे इंटरफ़ेस को संतुष्ट करता है।

आपके उदाहरण में, आप डेटा को टाइप कर रहे थे (टाइप इंटरफ़ेस {}) में कंक्रीट टाइप स्ट्रिंग है। यदि आप गलत हैं, तो प्रोग्राम रनटाइम में घबरा जाएगा। आपको दक्षता के बारे में चिंता करने की ज़रूरत नहीं है, जाँच करने के लिए बस दो पॉइंटर मानों की तुलना करने की आवश्यकता है।

यदि आप अनिश्चित थे यदि यह एक स्ट्रिंग था या नहीं, तो आप दो रिटर्न सिंटैक्स का उपयोग करके परीक्षण कर सकते हैं।

str, ok := data.(string)

यदि डेटा एक स्ट्रिंग नहीं है, तो ओके गलत होगा। यह इस तरह के एक बयान में एक आम बयान में लपेटने के लिए तो आम है:

if str, ok := data.(string); ok {
    /* act on str */
} else {
    /* not string */
}

29

टाइप टाइप करें

type assertionइसे गोलंग के रूप में जाना जाता है, और यह एक आम बात है।

यहाँ एक यात्रा से स्पष्टीकरण है :

एक प्रकार का अभिकथन इंटरफ़ेस मूल्य के अंतर्निहित ठोस मूल्य तक पहुँच प्रदान करता है।

t := i.(T)

यह कथन बताता है कि इंटरफ़ेस मान I ठोस प्रकार T रखता है और चर T को अंतर्निहित T मान प्रदान करता है।

यदि मैं एक टी नहीं रखता हूं, तो बयान एक आतंक को ट्रिगर करेगा।

यह जांचने के लिए कि क्या कोई इंटरफ़ेस मान एक विशिष्ट प्रकार रखता है, एक प्रकार का अभिकथन दो मान लौटा सकता है: अंतर्निहित मूल्य और एक बूलियन मान जो रिपोर्ट करता है कि क्या दावे सफल हुए।

t, ok := i.(T)

यदि मैं T धारण करता हूं, तो t अंतर्निहित मान होगा और ok सत्य होगा।

यदि नहीं, तो ओके गलत होगा और टी टाइप टी का शून्य मान होगा, और कोई घबराहट नहीं होती है।

नोट: मान iइंटरफ़ेस प्रकार होना चाहिए

नुकसान

भले ही iइंटरफ़ेस प्रकार है, []iइंटरफ़ेस प्रकार नहीं है। परिणामस्वरूप, []iइसके मूल्य प्रकार में बदलने के लिए, हमें इसे व्यक्तिगत रूप से करना होगा:

// var items []i
for _, item := range items {
    value, ok := item.(T)
    dosomethingWith(value)
}

प्रदर्शन

प्रदर्शन के लिए, यह वास्तविक मूल्य तक सीधी पहुंच की तुलना में धीमा हो सकता है जैसा कि इस स्टैकओवरफ़्लो उत्तर में दिखाया गया है ।


13
//an easy way:
str := fmt.Sprint(data)

21
जवाब के साथ कुछ स्पष्टीकरण जोड़ें कि यह उत्तर ओपी को वर्तमान मुद्दे को ठीक करने में कैसे मदद करता है
ρяєρ withя K

3

जैसा कि @ ρяσѕρєя द्वारा पूछा गया है एक स्पष्टीकरण https://golang.org/pkg/fmt/#Sprint पर पाया जा सकता है । संबंधित स्पष्टीकरण में पाया जा सकता https://stackoverflow.com/a/44027953/12817546 और कम से https://stackoverflow.com/a/42302709/12817546 । यहाँ पूर्ण रूप से @ युआनबो का जवाब है।

package main

import "fmt"

func main() {
    var data interface{} = 2
    str := fmt.Sprint(data)
    fmt.Println(str)
}

1
मुझे लगता है कि आप बस संपादन @ Yuanbo के द्वारा दोनों जवाब जोड़ सकता है - आप दोनों में जमा की जाएगी और अपने-अपने 'उपयोगिता' स्कोर 😉 जोड़
ग्वेनेथ लेवेलिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.