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

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)定义新变量
  • 使用XormStruct interface{}定义记录,并为每个ListOfTables条目创建一个 slice ,例如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
    

    最佳答案

    您可以使用 reflect.Type 表示/描述Go类型。并且在运行时,您可以使用 reflect.New() 获取指向包装在 reflect.Value 中的该类型的归零值的指针。而且,如果您需要 slice 而不是单个值,则可以使用 reflect.SliceOf() ,或者首先获取 slice 值的类型描述符。

    如果存储表的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)。

    如果首先要存储 slice 的Record值:
    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

    请注意,如果XormStruct保存 slice 类型(在Type.Elem()字段中),则是否需要访问结构的类型(结构的元素类型),可以为此使用ojit_code。

    08-06 00:54
    查看更多