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

标签 interface struct go field

使用 golang html/template(与 text/template 行为相同)。如果我有一个包含接口(interface)类型成员的结构,我无法访问基础类型的成员(特别是试图访问实现接口(interface) InnerInterface 但通过返回的结构上的字段InnerInterface 接口(interface)类型,不是结构类型)。

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 } 为完全通用的接口(interface),即 type MyOuterStruct struct { Inner interface{} } 使其正确呈现。这让我相信 interface{} 是由渲染引擎特殊处理的。

每当我希望能够像这样动态评估字段时,是否有比使用 interface{} 更好的方法来做到这一点?

最佳答案

您说 interface{} 以不同方式处理渲染是正确的 引擎。只有 interface{} 值被解压,没有设置方法的接口(interface)值。 我想这背后的原因是,如果你有一个接口(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
}

调用此方法以获取反射值的最深值。 假设你在一个指针上有一个指针,这个函数将返回 最后一个。接口(interface)值也是如此。关键是一旦 接口(interface)值有超过 0 个方法,间接到此为止。正是 您所描述的行为。

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

关于interface - 模板不会将接口(interface)类型的字段评估为基础类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19554209/

相关文章:

ios - 为结构创建变量 (Swift)

templates - Golang http/模板变量

http - 使用 PUT 方法在 Golang http 客户端请求中未设置 Content-Length header

c# - IComparable 和 IEquatable 接口(interface)有什么区别?

c++ - 将叶类重构为基类,同时保留它的接口(interface)实现

更改函数中传递的指针

go - 尝试从JSON响应中获取 “Total”的值

go - Windows 和 Linux 中的命名管道

java - 为什么我不能从 Scala 访问在实现 Java 接口(interface)的类中声明的变量?

Java lwjgl&slick2d 游戏 GUI 和 HUD?