存储有关结构的信息/参考 [英] Store information/reference about structure

查看:76
本文介绍了存储有关结构的信息/参考的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种存储信息的方法,该信息应构成函数应使用的结构.每个结构都对应于某些数据库表.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆