模板不会将接口类型的字段评估为基础类型

loading...


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{} 更好的方法呢?

1回答

  • 4

    你说 interface{} 由渲染引擎处理不同是正确的 . 仅解压缩 interface{} 值,不具有方法集的接口值 . 我想这背后的原因是,如果你有一个接口类型,你专门将类型限制为方法集 . 因此,您不希望模板引擎尝试访问可能位于该接口后面的成员 .

    'problem'是由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个方法,间接就会停在那里 . 正是你所描述的行为 .

    由于这似乎是预期的行为,你可以做的是在你的界面中定义一个 Title() string 方法,让它返回字符串 .

loading...

评论

暂时没有评论!