在go中结合row.Scan和rows.Scan接口?

时间:2014-01-13 15:56:50

标签: sql go

我对Go中的特定表有两个查询 - 一个用于检索单个项目而另一个用于返回列表。第一个使用sql.DB.QueryRow,因为它只需要检索一行,第二个使用sql.DB.Query返回一些不同的结果。

问题是序列化需要一些工作,我想通过一个从数据库行扫描并将其读入Go类型的方法来干掉它。我的代码现在看起来像:

// Some type which varies considerably from its DB representation, and takes some effort to serialize.
type Foo struct {
    Baz *Baz
    Board [8][8]int
}

// Get one foo by its id
func GetFoo(id int) {
    row := db.QueryRow("select * from foo where id = ?", id)
    // Work that's duplicated from below...
     var foo Foo
    row.Scan(&foo.blah, &foo.etc)
    // Do more work to serialize the type...
}

// Get all of the fooes
func GetFooes() {
    rows, err := db.Query("select * from foo")
    for rows.Next() {
        // Work that's duplicated from above...
        var foo Foo
        rows.Scan(&foo.blah, &foo.etc)
        // Do more work to serialize the type...
    }
}

然而,将row.Scan和rows.Scan结合起来证明有点棘手。我以为我可以使用类似的东西:

func serializeFoo(scanner sql.Scanner) (*Foo, error) {

}

虽然sql.Scanner只使用一个(value interface{})而不是(...value interface{})列表。

这里有什么建议吗?另一种解决方案是将单个QueryRow调用转换为db.Query

1 个答案:

答案 0 :(得分:1)

db.QueryRow是一个便利功能。除非它会节省打字/代码复杂性,否则没有理由使用它。在这种情况下,它不是,所以我建议你只使用db.Query。

有关详细信息,请参阅http://golang.org/src/pkg/database/sql/sql.go?s=25740:25802#L966


正如您所提到的,Row和Rows都没有实现Scanner界面。扫描仪用于变量扫描功能的参数。

如果您想要一个允许Row或Rows的参数,您需要创建自己的界面例如:

func serializeFoo(scanner interface{Scan(dest ...interface{}) error}) (*Foo, error) {

}