如何从嵌入式结构的方法中反映包含struct的字段?

问题描述 投票:2回答:2

这个程序的输出是map [],但我想要map [Id:true name:true]

我正在尝试干掉我的一些SQL CRUD代码,并认为嵌入一个处理读写数据库的持久性结构会很好。在下面的示例中,持久性结构将是Inner,我的模型将是Outer。谢谢!

http://play.golang.org/p/fsPqJ-6aLI
package main

import (
    "fmt"
    "reflect"
)

type Inner struct {
}

type Outer struct {
    Inner
    Id   int
    name string
}

func (i *Inner) Fields() map[string]bool {
    typ := reflect.TypeOf(*i)
    attrs := make(map[string]bool)

    if typ.Kind() != reflect.Struct {
        fmt.Printf("%v type can't have attributes inspected\n", typ.Kind())
        return attrs
    }

    // loop through the struct's fields and set the map
    for i := 0; i < typ.NumField(); i++ {
        p := typ.Field(i)
        if !p.Anonymous {
            v := reflect.ValueOf(p.Type)
            v = v.Elem()
            attrs[p.Name] = v.CanSet()

        }
    }

    return attrs
}

func main() {
    val := Outer{}
    fmt.Println(val.Fields()) // prints map[], but I want map[Id:true name:true]
}
go
2个回答
3
投票

你不能。你专门在Inner上调用一个方法,它不知道它嵌入的位置。嵌入不是继承,它是简单的自动委托。

您可能希望在公共持久性接口中查看这些包装的方向,或者甚至是可以处理持久化数据类型的通用函数。


现在,如果你真的想尝试这个,你可以通过指针地址访问外部结构,但是你需要知道你想要访问的外部类型,这意味着你无法通过反射获得它。

outer := (*Outer)(unsafe.Pointer(i))
typ := reflect.TypeOf(*outer)

0
投票

看起来你可以这样做:如果你创建一个接口并将有问题的对象作为arg传递给函数,则reflect会获得对象的正确外部类型:

package main

import (
    "fmt"
    "reflect"
)

type InType interface {
    Fields(obj InType) map[string]bool
}

type Inner struct {
}

type Outer struct {
    Inner
    Id   int
    name string
}

func (i *Inner) Fields(obj InType) map[string]bool {
    typ := reflect.TypeOf(obj).Elem()
    attrs := make(map[string]bool)

    if typ.Kind() != reflect.Struct {
        fmt.Printf("%v type can't have attributes inspected\n", typ.Kind())
        return attrs
    }

    // loop through the struct's fields and set the map
    for i := 0; i < typ.NumField(); i++ {
        p := typ.Field(i)
        if !p.Anonymous {
            v := reflect.ValueOf(p.Type)
            v = v.Elem()
            attrs[p.Name] = v.CanSet()

        }
    }

    return attrs
}

func main() {
    val := Outer{}
    fmt.Println(val.Fields(&val)) // prints map[Id:true name:true]
}

https://play.golang.org/p/0i3gNrMeSXa

© www.soinside.com 2019 - 2024. All rights reserved.