// Package sqlr ("squealer") provides some convenience wrappers around // database/sql in the spirit of encoding/json. package sqlr import ( "database/sql" "fmt" "reflect" ) // Scan calls rows.Scan to unpack a single row into the fields of v. func Scan(rows *sql.Rows, v any) error { rv := reflect.ValueOf(v) if rv.Kind() != reflect.Pointer || rv.Elem().Kind() != reflect.Struct { return fmt.Errorf("Scan needs a pointer to a struct") } inner := rv.Elem() fields := reflect.VisibleFields(inner.Type()) cols, err := rows.Columns() if err != nil { return err } dest := make([]any, len(cols)) Cols: for i, c := range cols { for _, f := range fields { if !f.IsExported() { continue } tag := f.Tag.Get("sql") if tag == "" { tag = f.Name } if tag == c { dest[i] = inner.FieldByIndex(f.Index).Addr().Interface() continue Cols } } return fmt.Errorf("no field with tag %q", c) } return rows.Scan(dest...) }