Documentation
¶
Overview ¶
Package scan provides functionality for scanning database/sql rows into slices, structs, and primitive types dynamically
Index ¶
- Variables
- func Columns(v interface{}, excluded ...string) ([]string, error)
- func ColumnsStrict(v interface{}, excluded ...string) ([]string, error)
- func Row(v interface{}, r RowsScanner) error
- func RowStrict(v interface{}, r RowsScanner) error
- func Rows(v interface{}, r RowsScanner) (outerr error)
- func RowsStrict(v interface{}, r RowsScanner) (outerr error)
- func Values(cols []string, v interface{}) ([]interface{}, error)
- type RowsScanner
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotAPointer is returned when a non-pointer is received // when a pointer is expected. ErrNotAPointer = errors.New("not a pointer") // ErrNotAStructPointer is returned when a non-struct pointer // is received but a struct pointer was expected ErrNotAStructPointer = errors.New("not a struct pointer") // ErrNotASlicePointer is returned when receiving an argument // that is expected to be a slice pointer, but it is not ErrNotASlicePointer = errors.New("not a slice pointer") // ErrStructFieldMissing is returned when trying to scan a value // to a column which does not match a struct. This means that // the struct does not have a field that matches the column // specified. ErrStructFieldMissing = errors.New("struct field missing") // ColumnsMapper transforms struct/map field names // into the database column names. // E.g. you can set function for convert CamelCase into snake_case ColumnsMapper = func(name string) string { return name } )
var ( // ErrTooManyColumns indicates that a select query returned multiple columns and // attempted to bind to a slice of a primitive type. For example, trying to bind // `select col1, col2 from mutable` to []string ErrTooManyColumns = errors.New("too many columns returned for primitive slice") // ErrSliceForRow occurs when trying to use Row on a slice ErrSliceForRow = errors.New("cannot scan Row into slice") // AutoClose is true when scan should automatically close Scanner when the scan // is complete. If you set it to false, then you must defer rows.Close() manually AutoClose = true // OnAutoCloseError can be used to log errors which are returned from rows.Close() // By default this is a NOOP function OnAutoCloseError = func(error) {} // ScannerMapper transforms database field names into struct/map field names // E.g. you can set function for convert snake_case into CamelCase ScannerMapper = func(name string) string { return cases.Title(language.English).String(name) } )
Functions ¶
func Columns ¶
Columns scans a struct and returns a list of strings that represent the assumed column names based on the db struct tag, or the field name. Any field or struct tag that matches a string within the excluded list will be excluded from the result.
Example ¶
var person struct { ID int `db:"person_id"` Name string } cols, _ := scan.Columns(&person) fmt.Printf("%+v", cols)
Output: [person_id Name]
Example (Exclude) ¶
var person struct { ID int `db:"id"` Name string `db:"name"` Age string `db:"-"` } cols, _ := scan.Columns(&person) fmt.Printf("%+v", cols)
Output: [id name]
func ColumnsStrict ¶
ColumnsStrict is identical to Columns, but it only searches struct tags and excludes fields not tagged with the db struct tag.
Example ¶
var person struct { ID int `db:"id"` Name string Age string `db:"age"` } cols, _ := scan.ColumnsStrict(&person) fmt.Printf("%+v", cols)
Output: [id age]
func Row ¶
func Row(v interface{}, r RowsScanner) error
Row scans a single row into a single variable. It requires that you use db.Query and not db.QueryRow, because QueryRow does not return column names. There is no performance impact in using one over the other. QueryRow only defers returning err until Scan is called, which is an unnecessary optimization for this library.
Example ¶
db := exampleDB() defer db.Close() rows, err := db.Query("SELECT id,name FROM person LIMIT 1") if err != nil { panic(err) } var person struct { ID int `db:"id"` Name string `db:"name"` } err = scan.Row(&person, rows) if err != nil { panic(err) } err = json.NewEncoder(os.Stdout).Encode(&person) if err != nil { panic(err) }
Output: {"ID":1,"Name":"brett"}
Example (Scalar) ¶
db := exampleDB() defer db.Close() rows, err := db.Query("SELECT name FROM person LIMIT 1") if err != nil { panic(err) } var name string err = scan.Row(&name, rows) if err != nil { panic(err) } fmt.Printf("%q", name)
Output: "brett"
func RowStrict ¶
func RowStrict(v interface{}, r RowsScanner) error
RowStrict scans a single row into a single variable. It is identical to Row, but it ignores fields that do not have a db tag
Example ¶
db := exampleDB() defer db.Close() rows, err := db.Query("SELECT id,name FROM person LIMIT 1") if err != nil { panic(err) } var person struct { ID int Name string `db:"name"` } err = scan.RowStrict(&person, rows) if err != nil { panic(err) } json.NewEncoder(os.Stdout).Encode(&person)
Output: {"ID":0,"Name":"brett"}
func Rows ¶
func Rows(v interface{}, r RowsScanner) (outerr error)
Rows scans sql rows into a slice (v)
Example ¶
db := exampleDB() defer db.Close() rows, err := db.Query("SELECT id,name FROM person ORDER BY id ASC") if err != nil { panic(err) } var persons []struct { ID int `db:"id"` Name *string `db:"name"` } err = scan.Rows(&persons, rows) if err != nil { panic(err) } json.NewEncoder(os.Stdout).Encode(&persons)
Output: [{"ID":1,"Name":"brett"},{"ID":2,"Name":"fred"},{"ID":3,"Name":null}]
Example (Primitive) ¶
db := exampleDB() defer db.Close() rows, err := db.Query("SELECT name FROM person WHERE name IS NOT NULL ORDER BY id ASC") if err != nil { panic(err) } var names []string err = scan.Rows(&names, rows) if err != nil { panic(err) } json.NewEncoder(os.Stdout).Encode(&names)
Output: ["brett","fred"]
func RowsStrict ¶
func RowsStrict(v interface{}, r RowsScanner) (outerr error)
RowsStrict scans sql rows into a slice (v) only using db tags
Example ¶
db := exampleDB() defer db.Close() rows, err := db.Query("SELECT id,name FROM person ORDER BY id ASC") if err != nil { panic(err) } var persons []struct { ID int Name *string `db:"name"` } err = scan.Rows(&persons, rows) if err != nil { panic(err) } json.NewEncoder(os.Stdout).Encode(&persons)
Output: [{"ID":0,"Name":"brett"},{"ID":0,"Name":"fred"},{"ID":0,"Name":null}]
func Values ¶
Values scans a struct and returns the values associated with the columns provided. Only simple value types are supported (i.e. Bool, Ints, Uints, Floats, Interface, String)
Example ¶
person := struct { ID int `db:"id"` Name string `db:"name"` }{ ID: 1, Name: "Brett", } cols := []string{"id", "name"} vals, _ := scan.Values(cols, &person) fmt.Printf("%+v", vals)
Output: [1 Brett]
Example (Nested) ¶
type Address struct { Street string City string } person := struct { ID int Name string Address }{ Name: "Brett", ID: 1, Address: Address{ City: "San Francisco", }, } cols := []string{"Name", "City"} vals, _ := scan.Values(cols, &person) fmt.Printf("%+v", vals)
Output: [Brett San Francisco]