2014-03-03 28 views
2

这个程序的输出为地图[],但我想图。[ID:真实姓名:真]如何从嵌入结构的方法反映包含结构的字段?

我想干涸我的一些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] 
} 

回答

3

你不能。您正在专门调用Inner上的方法,该方法不知道其嵌入的位置。嵌入不是继承,它是简单的自动委派。

您可能想要将它们包装在常见的持久性界面中,甚至是可以处理持久化数据类型的泛型函数。现在


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

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

我很努力,我知道我应该继续前进,但似乎你应该能够在运行时反映委托堆栈。 – Krut

+0

是的,信息只是不存在。如果你做了一个堆栈跟踪,你可以看到在val的地址上'Fields'被称为'(* Inner).Fields'。所以函数知道结构的地址,并且它至少是一个Inner,但看不到原始类型。 – JimB

0

好像你可以这样做:如果您创建一个接口,并通过所讨论的对象作为对Arg的功能,反映得到正确的外部对象的类型:

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