存储有关结构的信息/参考 [英] Store information/reference about structure
问题描述
我正在寻找一种存储信息的方法,该信息应构成函数应使用的结构.每个结构都对应于某些数据库表.
I am looking for a way to store information which struct a function should use. Each struct corresponds to certain database table.
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
}
我希望能够为表动态选择结构.
I want to be able to dynamically choose struct for table.
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张桌子,功能相同)
Goal DRY (I have about 30 tables, function is the same)
我尝试过:
-
以使用
reflect.TypeOf()
,但我不知道是否/如何使用它(reflect.Type
)定义新变量
to use
reflect.TypeOf()
, but I do not understand if/how I can use it (reflect.Type
) to define a new variable
用XormStruct interface{}
定义记录,并为每个ListOfTables条目创建一个切片,例如var posts []Post
和{"Post", "post_id", posts},
Define Record with XormStruct interface{}
and for each ListOfTables entry create a slice e.g. var posts []Post
and {"Post", "post_id", posts},
搜索SO和godocs
Searching SO and godocs
在我看来,xorm.Find()
对于获得interface{}
而不是[]Posts
并不高兴",即使它没有这么说.
It seems to me, that xorm.Find()
is not "happy" about getting an interface{}
instead of []Posts
even if it does not say so.
更新: 我相信最大的区别是:
UPDATE: I believe the breaking difference is this:
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()
,或首先获取切片值的类型描述符.
You may use reflect.Type
to represent / describe a Go type. And at runtime, you may use reflect.New()
to obtain a pointer to the zeroed value of this type wrapped in a reflect.Value
. And if you need a slice instead of a single value, you may use reflect.SliceOf()
, or obtain the type descriptor of the slice value in the first place.
如果存储表的refect.Type
值,则可以使用它:
If you store refect.Type
values of your tables, this is how you can use it:
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
}
请注意,您必须使用导出的字段!
Note you must use exported fields!
然后处理表:
for _, rec := range ListOfTables {
entries := reflect.New(reflect.SliceOf(t.XormStruct)).Interface()
err := xorm.Find(entries)
// Handle error
err := xml.Marshal(entries)
// Handle error
}
您可以使用JSON来查看此示例的工作示例(概念验证)(没有xorm
,因为Go Playground上没有此示例):
You can see a working example (proof of concept) of this (without xorm
as that is not available on the Go Playground) using JSON: Go Playground.
如果首先要存储切片的reflect.Type
值:
If you were to store reflect.Type
values of slices in the first place:
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
}
请参见以下概念证明:游乐场.
See proof of concept of this: Go Playground.
请注意,如果Record
保存切片类型(在字段XormStruct
中),则如果您需要访问结构的类型(结构的元素类型),则可以使用Type.Elem()
.
Note that if Record
holds slice types (in the field XormStruct
), should you ever need to access the type of the struct (the element type of the struct), you may use Type.Elem()
for that.
这篇关于存储有关结构的信息/参考的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!