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  }