【问题标题】:Store information/reference about structure存储有关结构的信息/参考
【发布时间】:2019-03-28 12:41:57
【问题描述】:

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

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
}

Goal DRY(我大概有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

【问题讨论】:

    标签: go struct reflection slice go-xorm


    【解决方案1】:

    您可以使用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
    }
    

    您可以使用 JSON:Go Playground 看到一个工作示例(概念证明)(没有 xorm,因为在 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()

    【讨论】:

    • 这两种方法都不会产生任何错误,但结果与我尝试存储 XormStruct interface{} 的结果相同。 xorm.Find(&amp;entries) 返回一个空的 &amp;[] 也许问题出在 xorm 本身?
    • @liepumartins 确保您的映射是正确的。例如,正如我在答案中指出的那样,您不能使用未导出的字段(您必须以大写字母开头的字段名称)。
    • 我确实导出了字段,抱歉,该部分的示例不正确。我更新了问题以说明我之前评论的意思。
    • 请发布使用我的解决方案但对您不起作用的确切代码。您在问题中包含的代码是我和您的解决方案的“混合”,甚至无法编译。还显示您是否以及如何处理错误。
    • 问题是 xorm.Find(&amp;entries) 应该是 xorm.Find(entries) 如果使用您的解决方案,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-26
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    相关资源
    最近更新 更多