使用带有结构的反射来构建通用处理程序函数

我在构建一个可以动态使用参数化结构的函数时遇到了一些麻烦。出于这个原因,我的代码有 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

}

所以嗯,我需要提供列表类型和普通类型作为参数,然后构建其中的一个,我的其余逻辑可能很容易修复。


绝地无双
浏览 164回答 1
1回答
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go