Хранить информацию / справку о структуре - PullRequest
0 голосов
/ 24 октября 2018

Я ищу способ хранения информации, которую должна использовать структура.Каждая структура соответствует определенной таблице базы данных.

type Record struct {
   TableName string
   PrimaryKey string
   //XormStruct // how can I store User or Post here?
   XormStruct2 interface{} // see I have tried below
   XormStruct3 reflect.Type // see I have tried below
}

var posts []Post

var ListOfTables [...]Record {
   {"User", "id", User},
   //{"Post", "post_id", Post},
   {"Post", "post_id", posts, reflect.TypeOf([]Post{})},
}

// User is xorm struct
type User struct {
   Id int64
   Name string
}

// Post is xorm struct
type Post struct {
   Post_id int64
   Name string
   Other string
}

Я хочу иметь возможность динамически выбирать структуру для таблицы.

for _, rec := range ListOfTables {
    //var entries []rec.XormStruct // this does not work, of course
    //var entries []reflect.TypeOf(rec.XormStruct) // this does not work either
    // xorm is *xorm.Engine
    xorm.Find(&entries)
    //xorm.Find(&rec.XormStruct2) //with interface{}, does not work - produces an empty &[]
    posts3 := reflect.New(rec.XormStruct3).Interface()
    //xorm.Find(&posts3) // same as above, produces empty &[]
    var posts []Post
    xorm.Find(&posts) // produces desired data

    // afterwards I will do same to any table entries, e.g.
    xml.Marshal(entries)
    // so there is really no need to create identical functions for each table
}

Цель СУХАЯ (у меня около 30 таблиц, функция - этото же самое)

Я пытался:

  • , чтобы использовать reflect.TypeOf(), но я не понимаю, могу ли я / как использовать его (reflect.Type) для определенияновая переменная

  • Определите запись с помощью XormStruct interface{} и для каждой записи ListOfTables создайте срез, например, var posts []Post и {"Post", "post_id", posts},

  • Поиск SOи godocs

Мне кажется, что xorm.Find() не "рад" получить interface{} вместо []Posts, даже если это не так.

ОБНОВЛЕНИЕ: Я считаю, что разница в разрыве заключается в следующем:

spew.Dump(posts3) //posts3 := reflect.New(rec.XormStruct3).Interface()
// (*[]main.Post)<0x2312312>(<nil>)
spew.Dump(posts) //var posts []Post
// ([]main.Post)<nil>

РЕШЕНИЕ

posts3 := reflect.New(rec.XormStruct3).Interface()
xorm.Find(posts3) // not &posts3

1 Ответ

0 голосов
/ 24 октября 2018

Вы можете использовать reflect.Type для представления / описания типа Go.А во время выполнения вы можете использовать reflect.New(), чтобы получить указатель на обнуленное значение этого типа, заключенное в reflect.Value.И если вам нужен срез вместо одного значения, вы можете использовать reflect.SliceOf() или получить дескриптор типа значения среза на первом месте.

Если вы храните refect.Type значения ваших таблиц, вот как вы можете их использовать:

type Record struct {
   TableName  string
   PrimaryKey string
   XormStruct reflect.Type
}

var ListOfTables [...]Record {
   {"User", "id", reflect.TypeOf((*User)(nil)).Elem()},
   {"Post", "post_id", reflect.TypeOf((*Post)(nil)).Elem()},
}

// User is xorm struct
type User struct {
   Id   int64
   Name string
}

// Post is xorm struct
type Post struct {
   Post_id int64
   Name    string
   Other   string
}

Обратите внимание, что вы должны использовать экспортированные поля!

А затем обрабатывать таблицы:

for _, rec := range ListOfTables {
    entries := reflect.New(reflect.SliceOf(t.XormStruct)).Interface()
    err := xorm.Find(entries)
    // Handle error

    err := xml.Marshal(entries)
    // Handle error
}

Вы можете увидеть рабочий пример (подтверждение концепции) этого (без xorm, поскольку он недоступен на Go Playground), используя JSON: Go Playground .

Если вы былидля хранения reflect.Type значений срезов в первую очередь:

var ListOfTables [...]Record {
   {"User", "id", reflect.TypeOf([]User{})},
   {"Post", "post_id", reflect.TypeOf([]Post{})},
}

И использовать его также проще:

for _, rec := range ListOfTables {
    entries := reflect.New(t.XormStruct).Interface()
    err := xorm.Find(entries)
    // Handle error

    err := xml.Marshal(entries)
    // Handle error
}

См. подтверждение концепции этого: Go Playground.

Обратите внимание, что если Record содержит типы срезов (в поле XormStruct), если вам когда-либо понадобится доступ к типу структуры (типу элемента структуры), вы можетеиспользуйте для этого Type.Elem().

...