package l_export_async import ( "context" "time" ) // PageStrategyType 分页策略类型 type PageStrategyType string const ( PageStrategyOffset PageStrategyType = "offset" PageStrategyCursor PageStrategyType = "cursor" PageStrategyTime PageStrategyType = "time" ) // PageStrategy 分页策略接口 type PageStrategy interface { // Type 类型标识 Type() PageStrategyType // InitialState 获取初始状态 InitialState() interface{} // NextPage 获取下一页数据 NextPage(ctx context.Context, state interface{}) ([][]interface{}, interface{}, error) // HasMore 是否还有下一页 HasMore(state interface{}, lastData [][]interface{}) bool // GetLimit 获取每批数据量 GetLimit() int } // DataFetcher 数据获取函数类型 type ( // OffsetDataFetcher 传统分页 OffsetDataFetcher func(ctx context.Context, pageNum, limit int) ([][]interface{}, error) // CursorDataFetcher 游标分页 CursorDataFetcher func(ctx context.Context, cursor interface{}, limit int) ([][]interface{}, interface{}, error) // TimeRangeDataFetcher 时间范围分页 TimeRangeDataFetcher func(ctx context.Context, startTime time.Time, limit int) ([][]interface{}, error) ) // OffsetStrategy 传统分页策略 type OffsetStrategy struct { fetcher OffsetDataFetcher limit int total int // 可选,用于提前知道总数 } func (s *OffsetStrategy) Type() PageStrategyType { return PageStrategyOffset } func (s *OffsetStrategy) InitialState() interface{} { return 1 // 初始页码 } func (s *OffsetStrategy) NextPage(ctx context.Context, state interface{}) ([][]interface{}, interface{}, error) { pageNum := state.(int) data, err := s.fetcher(ctx, pageNum, s.limit) if err != nil { return nil, nil, err } // 下一页页码 nextState := pageNum + 1 return data, nextState, nil } func (s *OffsetStrategy) HasMore(state interface{}, lastData [][]interface{}) bool { if s.total > 0 { currentPage := state.(int) totalPages := (s.total + s.limit - 1) / s.limit return currentPage <= totalPages } // 如果没有总数,则根据最后一页数据判断 //return len(lastData) >= s.limit //这里改为判断是否为空,多查一次 return len(lastData) > 0 } func (s *OffsetStrategy) GetLimit() int { return s.limit } // CursorStrategy 游标分页策略 type CursorStrategy struct { fetcher CursorDataFetcher limit int initialCursor interface{} } func (s *CursorStrategy) Type() PageStrategyType { return PageStrategyCursor } func (s *CursorStrategy) InitialState() interface{} { return s.initialCursor // nil 或初始游标值 } func (s *CursorStrategy) NextPage(ctx context.Context, state interface{}) ([][]interface{}, interface{}, error) { return s.fetcher(ctx, state, s.limit) } func (s *CursorStrategy) HasMore(state interface{}, lastData [][]interface{}) bool { // 这里如果为空,证明已经到最后一夜了 return len(lastData) > 0 } func (s *CursorStrategy) GetLimit() int { return s.limit } // TimeRangeStrategy 时间范围分页策略 type TimeRangeStrategy struct { fetcher TimeRangeDataFetcher limit int startTime time.Time endTime time.Time // 可选的结束时间 timeRange time.Duration // 每次查询的时间范围 lastQueryTime *time.Time // 记录最后一次查询的时间 } func (s *TimeRangeStrategy) Type() PageStrategyType { return PageStrategyTime } func (s *TimeRangeStrategy) InitialState() interface{} { return s.startTime } func (s *TimeRangeStrategy) NextPage(ctx context.Context, state interface{}) ([][]interface{}, interface{}, error) { currentTime := state.(time.Time) // 如果设置了结束时间,且当前时间已经超过结束时间 if !s.endTime.IsZero() && currentTime.After(s.endTime) { return nil, currentTime, nil } data, err := s.fetcher(ctx, currentTime, s.limit) if err != nil { return nil, nil, err } // 更新时间状态 var nextTime time.Time if len(data) > 0 { // 这里假设数据按时间排序,可以通过自定义逻辑来调整 nextTime = currentTime.Add(s.timeRange) } else { nextTime = currentTime.Add(s.timeRange) } s.lastQueryTime = ¤tTime return data, nextTime, nil } func (s *TimeRangeStrategy) HasMore(state interface{}, lastData [][]interface{}) bool { currentTime := state.(time.Time) // 如果设置了结束时间 if !s.endTime.IsZero() { return currentTime.Before(s.endTime) } return len(lastData) > 0 } func (s *TimeRangeStrategy) GetLimit() int { return s.limit }