-
-
Save narqo/48a4e6d492912195b3340dbecc65c2b0 to your computer and use it in GitHub Desktop.
An example snippet for the note https://vladimir.varank.in/notes/2022/05/a-real-life-use-case-for-generics-in-go-api-for-client-side-pagination/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pager | |
import "errors" | |
var PagerDone = errors.New("no more pages to iterate") | |
type pageIter[T any] interface { | |
NextPage() ([]T, error) | |
} | |
type fetchPageFunc[T any] func(page int) ([]T, PageInfo, error) | |
type Pager[T any] struct { | |
page int | |
pageInfo PageInfo | |
err error | |
fetchPage fetchPageFunc[T] | |
} | |
func NewPager[T any](page int, fetchPage fetchPageFunc[T]) *Pager[T] { | |
if page == 0 { | |
page = 1 | |
} | |
p := &Pager[T]{ | |
page: page, | |
fetchPage: fetchPage, | |
} | |
// hasNext must be set before the first interation | |
p.pageInfo.HasNext = true | |
return p | |
} | |
var _ pageIter[any] = (*Pager[any])(nil) | |
func (p *Pager[T]) NextPage() ([]T, error) { | |
var list []T | |
for len(list) == 0 { | |
if p.err != nil { | |
return nil, p.err | |
} | |
if !p.pageInfo.HasNext { | |
p.err = PagerDone | |
return nil, p.err | |
} | |
list, p.pageInfo, p.err = p.fetchPage(p.page) | |
p.page++ | |
} | |
return list, nil | |
} | |
func (p *Pager[T]) PageInfo() PageInfo { | |
return p.pageInfo | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pager | |
import ( | |
"math/rand" | |
"testing" | |
) | |
func TestPager(t *testing.T) { | |
pager := newTestPager(0) | |
n := rand.Intn(50) | |
for i := 1; i < n; i++ { | |
list, err := pager.NextPage() | |
if err != nil { | |
t.Fatal(err) | |
} | |
if len(list) != i { | |
t.Fatalf("page info: got list %+v", list) | |
} | |
pageInfo := pager.PageInfo() | |
if !pageInfo.HasNext { | |
t.Fatalf("pager: got page info %+v", pageInfo) | |
} | |
} | |
} | |
func newTestPager(init int) *Pager[int] { | |
var list []int | |
fetch := func(page int) ([]int, PageInfo, error) { | |
pageInfo := PageInfo{ | |
HasNext: true, | |
} | |
list = append(list, init+page) | |
return list, pageInfo, nil | |
} | |
return NewPager(0, fetch) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment