🐷

【Go】 BE制御 ページネーション実装

2024/12/01に公開

導入

ページネーションを実装する最も簡単な方法は、すべての一覧データをフロントエンドに返し、ページネーションの制御をフロントエンド側で行う方法です。しかし、この方法では、データ量が膨大になると、初回アクセス時のデータ取得やレンダリングに時間がかかる可能性があります。

この問題を解決する方法としては、ページごとにリクエストを送り、その都度データを取得してレンダリングする方法やSSGを活用して、事前にレンダリングしたデータを提供する方法があります。

今回は、ページごとにリクエストを送る方法について紹介します。

ページネーションの考え方

ページごとにデータを取得するためには、リクエストに以下のパラメータを含める必要があります:
limit:1ページあたりに表示するデータの件数。
offset:取得を開始するデータの位置。

例えば、フロントエンドで1ページに5件のデータを表示する場合、各ページに対応するlimitとoffsetの値は以下のようになります。

ページ番号 limit offset リクエスト例
1 5 0 GET /api/items?limit=5&offset=0
2 5 5 GET /api/items?limit=5&offset=5
3 5 10 GET /api/items?limit=5&offset=10
4 5 15 GET /api/items?limit=5&offset=15
5 5 20 GET /api/items?limit=5&offset=20

ページネーションの実装

実装はrepogitory層の実装は以下のようになります。ORMはentを使っています。countはページの最大値をFE側に表示するのに必要です。

func (c *client) AllTodos(ctx context.Context, input *repository.Input) (*repository.TodoGet, error) {	
	todos, err := c.client.Todo.
		Query().
		WithLabels().
		WithPriority().
		WithStatus().
		Limit(input.Limit).
		Offset(input.Offset).
		Order(ent.Desc("created_at")).
		All(ctx)
	if err != nil {
		return nil, err
	}

	count, err := c.client.Todo.
		Query().
		Count(ctx)
	if err != nil {
		return nil, err
	}

	return &repository.TodoGet{
		Todos:     todos,
		PageCount: count,
	}, nil
}

Discussion