2013-09-05 6 views
3

У меня есть:-структураПерейти: Как я могу «распаковать» структуру?

type mystruct struct { 
    Foo string 
    Bar int 
} 

я хотел бы создавать операторы SQL вставки из структур, которые имеют следующий вид:

m := mystruct{ "Hello" , 1 } 
query := "INSERT INTO mytbl (foo, bar) VALUES (?,?)" 
res,err := db.Exec(query, m.Foo, m.Bar) 

Теперь мой вопрос: как я могу сделать последний line динамически из самой структуры (или m)? Я могу получить имена структур, используя reflect, но я не знаю, как создать срез []interface{} для вызова db.Exec(). Это то, что я пробовал: (http://play.golang.org/p/GR1Bb61NFH)

package main 

import (
    "fmt" 
    "reflect" 
) 

type mystruct struct { 
    Foo string 
    Bar int 
} 

func main() { 
    m := mystruct{"Foo", 1} 
    fmt.Println(readNames(m)) 
    x := unpackStruct(m) 
    fmt.Printf("%#v\n", x) 
} 

func unpackStruct(a interface{}) []interface{} { 

    // "convert" a to m t 

    // doesn't work, from 'laws of reflection' 
    s := reflect.ValueOf(&t).Elem() 
    typeOfT := s.Type() 
    for i := 0; i < s.NumField(); i++ { 
     f := s.Field(i) 
     fmt.Printf("%d: %s %s = %v\n", i, 
      typeOfT.Field(i).Name, f.Type(), f.Interface()) 
    } 

    // this is in principle what I want: 
    m := mystruct{"Hello", 2} 
    var ret []interface{} 
    ret = make([]interface{}, s.NumField()) 
    ret[0] = m.Foo 
    ret[1] = m.Bar 
    return ret 
} 

// works fine: 
func readNames(a interface{}) []string { 
    s := reflect.TypeOf(a) 
    lenStruct := s.NumField() 
    ret := make([]string, lenStruct) 

    for i := 0; i < lenStruct; i++ { 
     ret[i] = s.Field(i).Name 
    } 
    return ret 
} 
+0

Я не очень понимаю, что ваше недоразумение было, так что я не буду отправлять полный ответ на сейчас, но ошибка в основном заключается в 's: = reflect.ValueOf (& t) .Elem()'. Строка излишне сложна, и я не уверен, что она делает, s: = reflect.ValueOf (a) отлично работает. http://play.golang.org/p/C9cv6uw97k – LinearZoetrope

+0

@ Joror, это именно то, что я хочу. Каким-то образом я не смог понять свое мнение в правильном направлении. Если вы опубликуете это как ответ, я буду рад «принять» его. – topskip

+0

Если аргумент 'a' предназначен для интерфейса, который может содержать любую структуру, то вы можете фактически передать' a' непосредственно в ValueOf, поскольку ValueOf принимает интерфейс в качестве аргумента: 's: = reflect.ValueOf (a) ' – joshlf

ответ

2

Если получать значения полей Ваш вопрос, этот фрагмент кода должен помочь:

s := reflect.ValueOf(a) 
ret := make([]interface{}, s.NumField()) 
for i := 0; i < s.NumField(); i++ { 
    ret[i] = s.Field(i).Interface() 
} 
0

При создании значения []interface{} ваша проблема, используя механизмы создания ломтика reflect «s должен работать хорошо:

slc := reflect.MakeSlice(InterfaceType, len, cap) // See the link below for creating InterfaceType 
slc.Index(0).Set(TargetValue) 
return slc.Interface() 

(Вот вышеупомянутая link).

Модифицировать приведенный выше код для циклического преобразования значений в структуре вместо 0-го индекса не должно быть слишком плохо.

+0

Я могу сделать интерфейс (' ret = make ([] interface {}, s.NumField()) 'в моем коде). Или мы говорим о разных вещах? Моя проблема заключается в том, как получить значения структуры. – topskip

+0

Да, я просто считаю, что делать это так проще и надежнее. Но если это ваша проблема (я неправильно понял ваш первоначальный вопрос), я буду пересказывать. – joshlf

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