2

I have two queries against a particular table in Go - one to retrieve a single item and the other to return a list. The first one uses sql.DB.QueryRow because it only needs to retrieve a single row, and the second one uses sql.DB.Query to return a few different results.

The problem is that serialization takes some work and I'd like to DRY it up by having a single method that scans from a database row and reads it into a Go type. My code right now looks like:

// 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...
    }
}

However combining row.Scan and rows.Scan is proving to be a little tricky. I thought I could use something like:

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

}

though sql.Scanner takes a single (value interface{}) and not a list of (...value interface{}).

Any advice here? Another solution would be to convert the single QueryRow call into a db.Query.

1 Answer 1

3

db.QueryRow is a convenience function. There is no reason to use it unless it will save on typing/code-complexity. In this case, it doesn't so I recommend you just use db.Query.

See http://golang.org/src/pkg/database/sql/sql.go?s=25740:25802#L966 for more details


As you mentioned, neither Row nor Rows implement the Scanner interface. Scanner is used for arguments of the variatic scan functions.

If you want to have a parameter that allows either Row or Rows, you need to make your own interface For example:

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

}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.