2013-12-10 20 views
0

我有以下查詢生成器功能:反映一個空的片段的領域Underyling類型?

func CreateQuery(t interface{}, where string) { 
    var b bytes.Buffer 
    b.WriteString("SELECT ") 

    s := reflect.ValueOf(t).Elem() 
    typeOfT := s.Type() 

    for i := 0; i < s.NumField() - 1; i++ { 
     b.WriteString(fmt.Sprintf("%s, ", typeOfT.Field(i).Name)) 
    } 

    //Last one has no Comma 
    b.WriteString(fmt.Sprintf("%s ", typeOfT.Field(s.NumField() - 1).Name)) 

    b.WriteString(fmt.Sprintf("FROM %s ", typeOfT.Name())) 
    b.WriteString(where) 
    fmt.Println(b.String()) 
} 

有正常工作的時候叫如下:

var dst FooStruct 
CreateQuery(&dst, "") 

但下面提出了「關於切片價值reflect.Value.NumField呼叫」恐慌:

var dst []FooStruct 
CreateQuery(&dst, "") 

我該如何讓該函數打印切片底層結構類型的字段?這似乎是我想要反映的SliceOf函數的反函數。

回答

3

您只能在代表結構(即t.Kind() == reflect.Struct)的reflect.Type上調用NumFieldField方法。

如果您有切片類型,則可以通過Elem方法訪問包含的類型,該方法返回另一個reflect.Type。如果切片包含一個結構,那麼您可以在這種類型上調用NumField/Field

+0

明白了,所以我需要做一些事情:'typeOfT:= s.Type()' ,然後'ContainedtypeOfT:= typeOfT.Elem()'。然後該函數的其餘部分引用'ContainedtypeOfT'而不是's'或'TypeofT' –

1

您可以通過切片迭代,呼籲CreateQuery,每次查詢:

func CreateQueries(t interface{}, where string) { 
    v := reflect.ValueOf(t) 

    if v.Kind() == reflect.Ptr { 
     v = v.Elem() 
    } 

    if v.Kind() == reflect.Array || v.Kind() == reflect.Slice { 
     for i := 0; i < v.Len(); i++ { 
      CreateQuery(v.Index(i).Interface(), where) 
     } 
    } 
} 

使用reflect.Value.Index您可以單獨訪問每個字段,在 值調用.Interface()產生該值的interface{}類型的代表,使之適合將 放入您的CreateQuery函數(該函數的值爲interface{})。

相關問題