mirror of
https://github.com/redis/go-redis.git
synced 2025-07-29 17:41:15 +03:00
Add scan iterator.
This commit is contained in:
committed by
Vladimir Mihailenco
parent
889409de38
commit
7456a0e473
75
iterator.go
Normal file
75
iterator.go
Normal file
@ -0,0 +1,75 @@
|
||||
package redis
|
||||
|
||||
import "sync"
|
||||
|
||||
type Scanner struct {
|
||||
client *commandable
|
||||
*ScanCmd
|
||||
}
|
||||
|
||||
// Iterator creates a new ScanIterator.
|
||||
func (s Scanner) Iterator() *ScanIterator {
|
||||
return &ScanIterator{
|
||||
Scanner: s,
|
||||
}
|
||||
}
|
||||
|
||||
// ScanIterator is used to incrementally iterate over a collection of elements.
|
||||
// It's safe for concurrent use by multiple goroutines.
|
||||
type ScanIterator struct {
|
||||
mu sync.Mutex // protects Scanner and pos
|
||||
Scanner
|
||||
pos int
|
||||
}
|
||||
|
||||
// Err returns the last iterator error, if any.
|
||||
func (it *ScanIterator) Err() error {
|
||||
it.mu.Lock()
|
||||
err := it.ScanCmd.Err()
|
||||
it.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// Next advances the cursor and returns true if more values can be read.
|
||||
func (it *ScanIterator) Next() bool {
|
||||
it.mu.Lock()
|
||||
defer it.mu.Unlock()
|
||||
|
||||
// Instantly return on errors.
|
||||
if it.ScanCmd.Err() != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Advance cursor, check if we are still within range.
|
||||
if it.pos < len(it.ScanCmd.page) {
|
||||
it.pos++
|
||||
return true
|
||||
}
|
||||
|
||||
// Return if there is more data to fetch.
|
||||
if it.ScanCmd.cursor == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// Fetch next page.
|
||||
it.ScanCmd._args[1] = it.ScanCmd.cursor
|
||||
it.ScanCmd.reset()
|
||||
it.client.Process(it.ScanCmd)
|
||||
if it.ScanCmd.Err() != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
it.pos = 1
|
||||
return len(it.ScanCmd.page) > 0
|
||||
}
|
||||
|
||||
// Val returns the key/field at the current cursor position.
|
||||
func (it *ScanIterator) Val() string {
|
||||
var v string
|
||||
it.mu.Lock()
|
||||
if it.ScanCmd.Err() == nil && it.pos > 0 && it.pos <= len(it.ScanCmd.page) {
|
||||
v = it.ScanCmd.page[it.pos-1]
|
||||
}
|
||||
it.mu.Unlock()
|
||||
return v
|
||||
}
|
Reference in New Issue
Block a user