【问题标题】:template won't evaluate fields that are interface type as the underlying type模板不会将接口类型的字段评估为基础类型
【发布时间】:2013-11-02 11:14:34
【问题描述】:

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

【问题讨论】:

    标签: interface struct go field


    【解决方案1】:

    你说得对,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
    }
    

    调用此方法以获取反射值的最深值。 假设你有一个指针上的指针,这个函数将返回 最后一个。接口值也是如此。关键是,一旦 接口值有多个方法,间接停止在那里。正是 你描述的行为。

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

    【讨论】:

    • 感谢这一点-就我的项目的结构而言,将 Title() 方法放在界面上是行不通的,但是是的,我得到了所涉及的因素。当我需要从模板轻松访问时,我最终使用了 interface{} 类型字段。它并不完美,但可行;并且很清楚发生了什么。
    猜你喜欢
    • 2020-11-09
    • 2023-02-07
    • 1970-01-01
    • 2019-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-18
    • 2015-09-14
    相关资源
    最近更新 更多