The Scanner interface (https://golang.org/pkg/database/sql/#Scanner) makes it quite easy to configure how a type is deserialized by the database/sql API from data that has been read from a database.
I've used this in various ways to handle my own types, but I just tried reading a denormalised string list into a slice of strings, e.g.
type Roles []string
func (rs Roles) Scan(value interface{}) error {
...
}
It's normal for the Scan receiver to be a pointer to a zero-valued instance of the type. In the case I'm trying to write, it's a slice instead.
Is this possible?
If so, how is the size of the slice determined (it isn't known until the scanner starts parsing, e.g. by splitting an input string on commas or something similar) ?
Yes, this is possible, but you want to define the method on *Roles instead. Then you can grow the slice as needed.
func (rs *Roles) Scan(value interface{}) error {
... check not nil
... split string into words
*rs = make(RosterRoles, len(words))
... range across the words
}
The database/sql library will be using this something like
var rs Roles
err := rs.Scan("abc,def")
// rs contains []string{"abc", "def"}
Thanks to @Peter for this answer.