我正在寻找一种存储信息的函数应该使用的结构的方法。每个结构对应于某些数据库表。
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 }
目标DRY(我大约有30张桌子,功能相同)
我努力了:
使用reflect.TypeOf(),但我不知道是否/如何使用它(reflect.Type)定义新变量
reflect.TypeOf()
reflect.Type
定义带有XormStruct interface{}每个ListOfTables条目的Record,并创建一个切片,例如var posts []Post和{"Post", "post_id", posts},
XormStruct interface{}
var posts []Post
{"Post", "post_id", posts},
搜索SO和godocs
在我看来,即使不是这样,xorm.Find()也不愿意“得到” 。interface{}``[]Posts
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
您可以reflect.Type用来表示/描述Go类型。并且在运行时,您可以使用reflect.New()来获取指向包装在中的该类型的零值的指针reflect.Value。并且,如果您需要切片而不是单个值,则可以使用reflect.SliceOf(),或者首先获取切片值的类型描述符。
reflect.New()
reflect.Value
reflect.SliceOf()
如果存储refect.Type表的值,则可以使用它:
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使用JSON:Go Playground看到一个可行的示例(概念证明)(没有Go Playground上没有的)。
xorm
如果首先要存储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 }
请参阅此概念证明:前往Playground。
请注意,如果Record保存切片类型(在字段中XormStruct),则如果您需要访问结构的类型(结构的元素类型),则可以使用Type.Elem()它。
Record
XormStruct
Type.Elem()