What I do myself is:
cols, _ = rows.Columns()
pointers := make([]interface{}, len(cols))
container := make([]sql.NullString, len(cols))
for i, _ := range dest {
pointers[i] = &container[i]
}
err = rows.Scan(pointers...)
You'll have a []interface{} which always points to the same index on
[]sql.NullString, and then you feed rows.Scan the pointers to your
container slice.
(sql.NullString is a struct that holds the data in one variable and
tells you if the data was null in another one)