2014-03-03 29 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