2013-12-10 3 views
0

я следующая функция конструктора запросов:Отражая поля пустых кусочков подстилающего типа?

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 на срез Значение» Panic :

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

Как я могу заставить функцию распечатать поля базового типа структуры среза? Похоже, я хочу, чтобы обратная функция отражения SliceOf.

ответ

3

можно вызывать только NumField или Field методов в reflect.Type представляющих-структуру (т.е. t.Kind() == reflect.Struct).

Если у вас есть тип среза, вы можете получить доступ к содержащемуся типу с помощью метода 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{}).

Смежные вопросы