Что такое пагинация?
Что проверяют
Умеете ли вы проектировать API списка: не определение, а выбор между смещением и курсором и понимание, чем этот выбор оборачивается для базы. В Go пагинацию обычно пишут руками, поэтому спросят и про построение запроса, и про контракт ответа.
Как отвечать
Пагинация это выдача коллекции порциями. Подходов два, и курсорная пагинация с keyset это одно и то же: курсор и есть закодированный ключ последней отданной строки, отдельного третьего способа нет.
Offset: LIMIT ? OFFSET ?. Плюс в произвольном доступе к странице, минус в том, что база честно читает и выбрасывает пропущенные строки, и на глубоких смещениях запрос проседает. Второй минус логический: при вставках между запросами страницы съезжают, элемент показывается дважды или пропадает.
Keyset: сортируем по паре из поля сортировки и первичного ключа и просим строки строго после последней виденной.
const q = `select id, created_at, title from jobs
where (created_at, id) < ($1, $2)
order by created_at desc, id desc
limit $3`
rows, err := db.QueryContext(ctx, q, cur.CreatedAt, cur.ID, limit+1)Приёмы, которые ценят: запрашивать на один элемент больше лимита, чтобы узнать о наличии следующей страницы без подсчёта; отдавать курсор непрозрачной строкой, например base64 от структуры, чтобы формат можно было менять; ограничивать лимит сверху и валидировать его.
Где спотыкаются
Фильтруют по одному полю сортировки без тайбрейкера. Если время создания у нескольких строк совпало, часть из них перепрыгнет границу страницы и не попадёт в выдачу никогда.
Считают общее количество на каждый запрос. Подсчёт по таблице с фильтром нередко дороже самой выборки; если точное число не требуется контрактом, его лучше не отдавать или оценивать приблизительно.
Кладут в курсор сырой идентификатор или смещение и закрепляют это в публичном контракте. Клиенты начинают собирать курсоры сами, и поменять порядок сортировки без поломки интеграций уже невозможно.