我在构建一个可以动态使用参数化结构的函数时遇到了一些麻烦。出于这个原因,我的代码有 20 多个相似的函数,除了基本上使用的一种类型。我的大部分经验是使用 Java,我只是开发基本的通用函数,或者使用普通的 Object 作为函数的参数(以及从那时起的反射)。我需要类似的东西,使用 Go。
我有几种类型,例如:
// The List structs are mostly needed for json marshalling
type OrangeList struct {
Oranges []Orange
}
type BananaList struct {
Bananas []Banana
}
type Orange struct {
Orange_id string
Field_1 int
// The fields are different for different types, I am simplifying the code example
}
type Banana struct {
Banana_id string
Field_1 int
// The fields are different for different types, I am simplifying the code example
}
然后我有功能,基本上每个列表类型:
// In the end there are 20+ of these, the only difference is basically in two types!
// This is very un-DRY!
func buildOranges(rows *sqlx.Rows) ([]byte, error) {
oranges := OrangeList{} // This type changes
for rows.Next() {
orange := Orange{} // This type changes
err := rows.StructScan(&orange) // This can handle each case already, could also use reflect myself too
checkError(err, "rows.Scan")
oranges.Oranges = append(oranges.Oranges,orange)
}
checkError(rows.Err(), "rows.Err")
jsontext, err := json.Marshal(oranges)
return jsontext, err
}
是的,我可以更改 sql 库以使用更智能的 ORM 或框架,但这不是重点。我想学习如何构建可以为所有不同类型处理类似功能的通用函数。
我走了这么远,但它仍然无法正常工作(我认为目标不是预期的结构):
func buildWhatever(rows *sqlx.Rows, tgt interface{}) ([]byte, error) {
tgtValueOf := reflect.ValueOf(tgt)
tgtType := tgtValueOf.Type()
targets := reflect.SliceOf(tgtValueOf.Type())
for rows.Next() {
target := reflect.New(tgtType)
err := rows.StructScan(&target) // At this stage target still isn't 1:1 smilar struct so the StructScan fails... It's some perverted "Value" object instead. Meh.
// Removed appending to the list because the solutions for that would be similar
checkError(err, "rows.Scan")
}
checkError(rows.Err(), "rows.Err")
jsontext, err := json.Marshal(targets)
return jsontext, err
}
所以嗯,我需要提供列表类型和普通类型作为参数,然后构建其中的一个,我的其余逻辑可能很容易修复。
相关分类