github.com/kunlun-qilian/sqlx/v3@v3.0.0/scanner/iterators.go (about) 1 package scanner 2 3 import ( 4 "reflect" 5 6 reflectx "github.com/go-courier/x/reflect" 7 ) 8 9 type ScanIterator interface { 10 // New a ptr value for scan 11 New() interface{} 12 // Next For receive scanned value 13 Next(v interface{}) error 14 } 15 16 func ScanIteratorFor(v interface{}) (ScanIterator, error) { 17 switch x := v.(type) { 18 case ScanIterator: 19 return x, nil 20 default: 21 tpe := reflectx.Deref(reflect.TypeOf(v)) 22 23 if tpe.Kind() == reflect.Slice && tpe.Elem().Kind() != reflect.Uint8 { 24 return &SliceScanIterator{ 25 elemType: tpe.Elem(), 26 rv: reflectx.Indirect(reflect.ValueOf(v)), 27 }, nil 28 } 29 30 return &SingleScanIterator{target: v}, nil 31 } 32 } 33 34 type SliceScanIterator struct { 35 elemType reflect.Type 36 rv reflect.Value 37 } 38 39 func (s *SliceScanIterator) New() interface{} { 40 return reflectx.New(s.elemType).Addr().Interface() 41 } 42 43 func (s *SliceScanIterator) Next(v interface{}) error { 44 s.rv.Set(reflect.Append(s.rv, reflect.ValueOf(v).Elem())) 45 return nil 46 } 47 48 type SingleScanIterator struct { 49 target interface{} 50 hasResults bool 51 } 52 53 func (s *SingleScanIterator) New() interface{} { 54 return s.target 55 } 56 57 func (s *SingleScanIterator) Next(v interface{}) error { 58 s.hasResults = true 59 return nil 60 } 61 62 func (s *SingleScanIterator) MustHasRecord() bool { 63 return s.hasResults 64 }