在这两个迭代器中减少重复的好方法是什么?

I wrote an iterator for easier access to some paged DB results but what's a good way to reduce the duplication?

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
}

Usage

fooIterator := NewFooIterator(a, 100)

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

They're both so similar there must be some good way to share code but everything I have tried seems awkward.

Write a common iterator that calls a function to get more data:

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
}

Use it like this:

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
}