检查结构体是否在运行时具有嵌入结构体

3
假设我有以下结构体:
type Room struct {
  BaseModel
}

func main() {
  r := Room{}
}

在代码的其他地方,我获取了一个名为r的对象。它可能是 Room 或其他东西。我想在运行时检查r的类(在本例中是Room)是否嵌入了BaseModel结构体。这是否可行?


BaseModel是Room的一个100%普通字段,名称为“BaseModel”。reflect.TypeOf(r).FieldByName("BaseModel")将返回该字段或零值(如果没有这样的字段)。您想在运行时确定的任何内容都是通过反射包完成的,并且嵌入会产生普通字段。很明显,不是吗? - Volker
这个问题让我想到你想要构建某种继承并将Room多态化为BaseModel。请注意,Go不支持继承有其合理的原因。考虑使用组合或声明所需行为的接口。即使Room拥有一个BaseModel,它也不是一个BaseModel,就像你期望的那样使用继承一样。 - Bazzz
2个回答

2

是的,您可以使用反射在运行时检查。以下是一个非常简单的示例,它使用reflect.TypeOf来打印嵌入结构Foo的结构Bar的每个字段的类型,并且还使用reflect.ValueOf来打印字段是否是匿名的(true)或不是 - 这是您所要求的良好指标:

package main

import (
    "fmt"
    "reflect"
)

type Foo struct {
    foo string
}

type Bar struct {
    Foo
    bar string
}

func main() {
    test := Bar{}
    t := reflect.TypeOf(test)

    for i := 0; i < t.NumField(); i++ {
        fmt.Print(t.Field(i).Type, " ")
        fmt.Println(reflect.ValueOf(t.Field(i).Anonymous))
    }
}

这是在playground上的代码:https://play.golang.org/p/zNWxZUzq_RS

您没有询问具体要做什么,因此将更先进的用法指向reflect文档


2

检查reflect.StructFieldAnonymous字段。

func embedsBaseModel(v interface{}) bool {
    rt := reflect.TypeOf(v)
    if rt.Kind() != reflect.Struct {
        return false
    }

    base := reflect.TypeOf(BaseModel{})
    for i := 0; i < rt.NumField(); i++ {
        if sf := rt.Field(i); sf.Type == base && sf.Anonymous {
            return true
        }
    }
    return false
}

https://play.golang.com/p/-6flZcdSYwj


为什么不提出一个解决方案,该方案由basemodel上的私有方法和一个接口组成,以进行类型断言? - user4466350
如果您认为这是一个有效的,即使不是“最佳”的解决方案,您应该将其发布为答案。也许OP会更喜欢它而不是其他选择,如果不是OP,那么也许一些其他开发人员在以后的某个时间可能会喜欢它。 - mkopriva
@mh-cbon 顺便提一句,如果 BaseModel 不是你的而是第三方类型,那么你的解决方案将不起作用。 - mkopriva
是的,我同意最后那个声明。另一方面,如果你拥有该类型,它将更加高效。无论如何,我不想回答那个帖子,只是想听听你的想法。 - user4466350

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接