Какой хороший способ уменьшить дублирование в этих двух итераторах? - PullRequest
0 голосов
/ 10 мая 2018

Я написал итератор для более легкого доступа к некоторым постраничным результатам БД, но как можно уменьшить дублирование?

foo_iterator.go

type FooIterator struct {
    hasNext   bool
    app       *App
    batchSize int
}

func NewFooIterator(app *App, batchSize int) *FooIterator {
    return &FooIterator{
        hasNext:   true,
        app:       app,
        batchSize: batchSize,
    }
}

func (it *FooIterator) HasNext() bool {
    return it.hasNext
}

func (it *FooIterator) Next() []*model.Foo {
    offset := 0
    batch := it.app.GetAllFoosInPages(offset, it.batchSize)
    if len(batch) < it.batchSize {
        it.hasNext = false
    }
    offset += it.batchSize
    return batch
}

bar_iterator.go

type BarIterator struct {
    hasNext   bool
    app       *App
    batchSize int
}

func NewBarIterator(app *App, batchSize int) *BarIterator {
    return &BarIterator{
        hasNext:   true,
        app:       app,
        batchSize: batchSize,
    }
}

func (it *BarIterator) HasNext() bool {
    return it.hasNext
}

func (it *BarIterator) Next() []*model.Bar {
    offset := 0
    batch := it.app.GetAllBarsInPages(offset, it.batchSize)
    if len(batch) < bi.batchSize {
        it.hasNext = false
    }
    offset += it.batchSize
    return batch
}

Использование

fooIterator := NewFooIterator(a, 100)

for fooIterator.HasNext() {
    fooBatch := rolesIterator.Next()
    // Do stuff
}

Они оба настолько похожи, что должен быть какой-то хороший способ поделиться кодом, но все, что я пробовал, кажется неловким.

1 Ответ

0 голосов
/ 10 мая 2018

Напишите общий итератор, который вызывает функцию для получения дополнительных данных:

type Iterator struct {
    more      func(offset int, batchSize int) (int, interface{})
    hasNext   bool
    batchSize int
    offset    int
}

func (it *Iterator) HasNext() bool {
    return it.hasNext
}

func (it *Iterator) Next() interface{} {
    n, batch := it.more(it.offset, it.batchSize)
    if n < it.batchSize {
        it.hasNext = false
    }
    it.offset += n
    return batch
}

Используйте это так:

func NewFooIterator(app *App, batchSize int) *Iterator {
    return &Iterator{
        hasNext:   true,
        batchSize: batchSize,
        more: func(offset int, batchSize int) (int, interface{}) {
            batch := it.app.GetAllFoosInPages(offset, it.batchSize)
            return len(batch), batch
        },
    }
}

fooIterator := NewFooIterator(a, 100)

for fooIterator.HasNext() {
    fooBatch := fooIterator.Next().([]*model.Foo)
    // Do stuff
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...