This document describes the comprehensive pagination support implemented in the Yandex Disk Go client library.
The pagination system provides multiple ways to handle large result sets from the Yandex Disk API:
- Basic Pagination - Simple offset/limit-based pagination
- Enhanced Pagination - Pagination with metadata and status information
- Iterator Pattern - Convenient iteration over paginated results
- Cursor-based Pagination - Future-ready cursor support
Get a sorted list of files with pagination support.
Basic Usage:
// Get first 20 files (default)
files, err := client.GetSortedFiles(ctx)
// Get with custom pagination
options := &disk.PaginationOptions{
Limit: 10,
Offset: 20,
}
files, err := client.GetSortedFilesWithPagination(ctx, options)Enhanced Pagination:
options := &disk.PaginationOptions{Limit: 15}
pagedFiles, err := client.GetSortedFilesPaged(ctx, options)
if err == nil {
fmt.Printf("Files: %d\n", len(pagedFiles.Items))
fmt.Printf("HasMore: %t\n", pagedFiles.Pagination.HasMore)
if pagedFiles.Pagination.HasMore {
fmt.Printf("NextOffset: %d\n", pagedFiles.Pagination.NextOffset)
}
}Iterator Pattern:
iterator := client.GetSortedFilesIterator(&disk.PaginationOptions{Limit: 10})
for iterator.HasNext() {
page, err := iterator.Next(ctx)
if err != nil {
break
}
for _, file := range page.FilesResourceList.Items {
fmt.Printf("File: %s\n", file.Name)
}
}Get recently uploaded files with pagination.
// Basic pagination
files, err := client.GetLastUploadedResources(ctx)
// With custom options
options := &disk.PaginationOptions{Limit: 5}
files, err := client.GetLastUploadedResourcesWithPagination(ctx, options)
// Enhanced with pagination info
pagedFiles, err := client.GetLastUploadedResourcesPaged(ctx, options)
// Iterator pattern
iterator := client.GetLastUploadedResourcesIterator(options)Get public resources with pagination.
// Basic pagination
resources, err := client.GetPublicResources(ctx)
// With custom options
options := &disk.PaginationOptions{Limit: 10}
resources, err := client.GetPublicResourcesWithPagination(ctx, options)
// Enhanced with pagination info
pagedResources, err := client.GetPublicResourcesPaged(ctx, options)
// Iterator pattern
iterator := client.GetPublicResourcesIterator(options)type PaginationOptions struct {
Limit int // Maximum number of items to return (default: 20, max: 10000)
Offset int // Number of items to skip from the beginning (default: 0)
Cursor string // Cursor for cursor-based pagination (optional)
}- Limit: 20 items per page
- Offset: 0 (start from beginning)
- Maximum Limit: 10000 items per page
All pagination options are automatically validated:
- Negative or zero limits default to 20
- Limits exceeding 10000 are capped at 10000
- Negative offsets are set to 0
type PaginationInfo struct {
Limit int // Number of items requested
Offset int // Number of items skipped
Total int // Total number of items available (when available)
HasMore bool // Whether there are more items available
NextOffset int // Offset for the next page
NextCursor string // Cursor for the next page (cursor-based pagination)
PrevCursor string // Cursor for the previous page (cursor-based pagination)
}iterator := client.GetSortedFilesIterator(&disk.PaginationOptions{Limit: 25})
for iterator.HasNext() {
page, err := iterator.Next(ctx)
if err != nil {
log.Printf("Error: %v", err)
break
}
// Process page.FilesResourceList.Items
for _, file := range page.FilesResourceList.Items {
fmt.Printf("Processing: %s\n", file.Name)
}
// Optional: Add delay to respect rate limits
time.Sleep(200 * time.Millisecond)
}iterator := client.GetSortedFilesIterator(nil)
// Change page size
iterator.SetPageSize(50)
// Check current settings
pageSize := iterator.GetPageSize()
currentOffset := iterator.GetCurrentOffset()
// Reset to beginning
iterator.Reset()fetcher := func(ctx context.Context, cursor string, limit int) (*disk.PagedFilesResourceList, string, error) {
// Custom fetcher implementation
// Return: (data, nextCursor, error)
}
cursorIterator := disk.NewCursorPaginationIterator(client, fetcher, 20)
for cursorIterator.HasNext() {
page, err := cursorIterator.Next(ctx)
if err != nil {
break
}
// Process page
}func collectAllFiles(client *disk.Client, ctx context.Context) ([]*disk.Resource, error) {
var allFiles []*disk.Resource
iterator := client.GetSortedFilesIterator(&disk.PaginationOptions{Limit: 100})
for iterator.HasNext() {
page, err := iterator.Next(ctx)
if err != nil {
return nil, err
}
allFiles = append(allFiles, page.FilesResourceList.Items...)
// Respect rate limits
time.Sleep(100 * time.Millisecond)
}
return allFiles, nil
}func searchFiles(client *disk.Client, ctx context.Context, pattern string) ([]*disk.Resource, error) {
var matches []*disk.Resource
iterator := client.GetSortedFilesIterator(&disk.PaginationOptions{Limit: 50})
for iterator.HasNext() {
page, err := iterator.Next(ctx)
if err != nil {
return nil, err
}
for _, file := range page.FilesResourceList.Items {
if strings.Contains(strings.ToLower(file.Name), strings.ToLower(pattern)) {
matches = append(matches, file)
}
}
time.Sleep(200 * time.Millisecond)
}
return matches, nil
}// Different page sizes for different use cases
smallPages := &disk.PaginationOptions{Limit: 5} // For UI display
mediumPages := &disk.PaginationOptions{Limit: 50} // For processing
largePages := &disk.PaginationOptions{Limit: 1000} // For bulk operations
// Use with any paginated method
files1, _ := client.GetSortedFilesWithPagination(ctx, smallPages)
files2, _ := client.GetLastUploadedResourcesWithPagination(ctx, mediumPages)
files3, _ := client.GetPublicResourcesWithPagination(ctx, largePages)Always add delays between API calls to respect rate limits:
iterator := client.GetSortedFilesIterator(&disk.PaginationOptions{Limit: 20})
for iterator.HasNext() {
page, err := iterator.Next(ctx)
if err != nil {
break
}
// Process page...
// Add delay between requests
time.Sleep(200 * time.Millisecond)
}iterator := client.GetSortedFilesIterator(nil)
for iterator.HasNext() {
page, err := iterator.Next(ctx)
if err != nil {
log.Printf("Error fetching page: %v", err)
// Decide whether to continue or abort
if isTemporaryError(err) {
time.Sleep(1 * time.Second)
continue
} else {
break
}
}
// Process page...
}ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
iterator := client.GetSortedFilesIterator(&disk.PaginationOptions{Limit: 10})
for iterator.HasNext() {
select {
case <-ctx.Done():
log.Printf("Operation cancelled: %v", ctx.Err())
return
default:
page, err := iterator.Next(ctx)
if err != nil {
break
}
// Process page...
}
}For large datasets, process pages individually rather than collecting all results:
// Good: Process each page individually
iterator := client.GetSortedFilesIterator(&disk.PaginationOptions{Limit: 100})
for iterator.HasNext() {
page, err := iterator.Next(ctx)
if err != nil {
break
}
// Process and discard page
processFiles(page.FilesResourceList.Items)
// page goes out of scope and can be garbage collected
}
// Avoid: Collecting all results in memory for large datasets
// var allFiles []*disk.Resource // This could consume too much memoryThe original methods are preserved for backward compatibility:
// Old way (still works)
files, err := client.GetSortedFiles(ctx)
// New way with explicit pagination
files, err := client.GetSortedFilesWithPagination(ctx, &disk.PaginationOptions{Limit: 20})
// Enhanced way with pagination info
pagedFiles, err := client.GetSortedFilesPaged(ctx, &disk.PaginationOptions{Limit: 20})The pagination system is designed to support future API enhancements:
- Cursor-based Pagination - Ready for when the API supports cursors
- Total Count Support - Will utilize total counts when available
- Sorting Options - Can be extended to support different sort orders
- Filtering - Framework ready for server-side filtering
All pagination methods return appropriate error types:
files, errResp := client.GetSortedFilesWithPagination(ctx, options)
if errResp != nil {
switch errResp.Error {
case "UnauthorizedError":
// Handle authentication issues
case "LimitExceededError":
// Handle rate limiting
default:
// Handle other errors
}
}- Page Size: Balance between fewer requests (larger pages) and memory usage
- Rate Limits: Always include delays between requests
- Context Timeouts: Set appropriate timeouts for large operations
- Error Retry: Implement retry logic for temporary failures
- Memory Usage: Process pages individually for large datasets
Comprehensive tests are provided for all pagination functionality:
# Run pagination-specific tests
go test -v -run TestPagination
# Run all tests to ensure compatibility
go test -vSee examples/pagination_example.go for a complete working example demonstrating all pagination features.