2013-10-30 7 views
8

खेल का मैदान लिंक: http://play.golang.org/p/Ebf5AuJlcPइंटरफेस में असंबंधित विधि की उपस्थिति पाठ/टेम्पलेट तोड़ती है?

type Foo interface {} 

type Bar interface { 
    ThisIsABar() 
} 

// Person implements both Foo and Bar 
type Person struct { 
    Name string 
} 

func (p Person) ThisIsABar() {} 

type FooContext struct { 
    Something Foo 
} 

type BarContext struct { 
    Something Bar 
} 

func main() { 
    t := template.Must(template.New("test").Parse("{{ .Something.Name }}\n")) 

    // This works fine. 
    if err := t.Execute(os.Stdout, FooContext{Person{"Timmy"}}); err != nil { 
     fmt.Printf("Error: %s\n", err) 
    } 

    // With BarContext, containing the exact same Person but wrapped in a 
    // different interface, it errors out. 
    if err := t.Execute(os.Stdout, BarContext{Person{"Timmy"}}); err != nil { 
     fmt.Printf("Error: %s\n", err) 
    } 
} 

जब मैं (text/template पैकेज के माध्यम से) एक टेम्पलेट {{ .Something.Name }} युक्त प्रस्तुत करना, मैं इंटरफ़ेस Foo जो कोई तरीकों में शामिल है के माध्यम से जा सकते हैं, और यह ठीक काम करता है। लेकिन अगर मैं इंटरफ़ेस Bar के माध्यम से के बजाय जाओ, मैं मिलता है:

executing "test" at <.Something.Name>: can't evaluate field Name in type main.Bar 

क्यों इंटरफेस पर एक असंबंधित विधि की उपस्थिति, कि यहां तक ​​कि नहीं किया जाता है, टेम्पलेट का प्रतिपादन प्रभावित करता है?

+1

संभावित डुप्लिकेट [टेम्पलेट उन क्षेत्रों का मूल्यांकन नहीं करेगा जो इंटरफ़ेस प्रकार अंतर्निहित प्रकार के रूप में हैं] (http://stackoverflow.com/questions/19554209/template-wont-evaluate-fields-that-are-interface-type -as-the-underlying-type) – nemo

उत्तर

6

टेक्स्ट/टेम्पलेट विशेष आवरण इंटरफ़ेस {} है, इसलिए फ़ंक्शंस फ़ंक्शंस में रिटर्न टाइप इंटरफ़ेस {} इत्यादि हो सकता है। आपके इंटरफ़ेस में एक विधि जोड़ना मतलब है कि पहचान अब ट्रिगर नहीं होती है।

http://golang.org/src/pkg/text/template/exec.go#L323

323  for _, cmd := range pipe.Cmds { 
324   value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg. 
325   // If the object has type interface{}, dig down one level to the thing inside. 
326   if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 { 
327    value = reflect.ValueOf(value.Interface()) // lovely! 
328   } 
329  } 

BarContext.Something एक बार (एक अंतरफलक) है। एक बार में कोई फ़ील्ड नाम नहीं है। यदि आप वहां एक इंटरफ़ेस का उपयोग करना चाहते हैं, तो आपको डेटा को एक विधि के माध्यम से प्रदान करना होगा जो इंटरफ़ेस का हिस्सा है।

+0

क्या आपने सत्यापित किया था कि यह कोड व्यवहार के लिए ज़िम्मेदार है? मुझे लगता है कि यह ['अप्रत्यक्ष '] के कार्यान्वयन के बजाय है (http://stackoverflow.com/a/19555267/1643939)। लेकिन शायद मुझे कुछ याद आया। – nemo

+0

वाह, यह अप्रत्याशित है। मुझे किसी भी तरह से http://stackoverflow.com/questions/19554209/template-wont-evaluate-fields-that-are-interface-type-as-the-underlying-type नहीं मिला लेकिन एक ही समाधान के साथ समाप्त हुआ: बस टेम्पलेट में चीजें पास करते समय 'इंटरफ़ेस {}' का उपयोग करें। – Thomas

संबंधित मुद्दे