2013-10-23 91 views
4

使用golang html/template(與text/template的行爲相同)。如果我有一個具有接口類型的成員的結構體,我無法訪問基礎類型的成員(特別是試圖訪問結構體上實現接口InnerInterface但通過InnerInterface接口類型返回的字段,而不是結構體類型)。模板不會評估接口類型爲基礎類型的字段

http://play.golang.org/p/ZH8wSK83oM

package main 

import "fmt" 
import "os" 
import "html/template" 

type InnerInterface interface{ InnerSomeMethod() } 

type MyInnerStruct struct { Title string } 
func (mis MyInnerStruct)InnerSomeMethod() { fmt.Println("Just to show we're satisfying the interface") } 

type MyOuterStruct struct { Inner InnerInterface } 


func main() { 

    fmt.Println("Starting") 


    arg := MyOuterStruct{Inner:MyInnerStruct{Title:"test1"}} 

    err := template.Must(template.New("testtmpl").Parse("{{.Inner.Title}}")).Execute(os.Stdout, arg) 
    if err != nil { panic(err) } 

} 

更改:type MyOuterStruct struct { Inner InnerInterface }一個完全通用的接口,即type MyOuterStruct struct { Inner interface{} }使它呈現正常。這使我相信interface{}被渲染引擎專門處理。

有沒有更好的方法來做到這一點,而不是使用interface{}每當我想能夠動態評估這樣的領域?

回答

4

你說的正確,interface{}由渲染 引擎處理不同。只有interface{}值解包,有方法設置的接口值不是。 我想這背後的原因是,如果你有一個接口類型,你特別限制類型的方法集。因此,您不希望模板引擎嘗試訪問可能位於該接口後面的成員。

「問題」是由函數indirect in exec.go引起:

func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { 
    for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() { 
     if v.IsNil() { 
      return v, true 
     } 
     if v.Kind() == reflect.Interface && v.NumMethod() > 0 { 
      break 
     } 
    } 
    return v, false 
} 

這種方法被稱爲去的反射值的最深的值。 假設你有一個指針指針上的指針,這個函數將返回 其中的最後一個。接口值也是一樣。關鍵在於,只要接口值有多於0個方法,則間接就停在此處。您正在描述的行爲恰恰是 。

由於這似乎是預期的行爲,你可以做的是在你的接口中定義一個方法,讓它返回字符串。

+0

Tks for this - 就我的項目結構而言,它不能將Title()方法放在界面上,但是我得到了涉及的因素。當我需要從模板中輕鬆訪問時,我最終使用了接口{}類型字段。這並不完美,但可行;而且很清楚發生了什麼事情。 –

相關問題