go get github.com/dpwgc/go-filesort
package main
import (
"fmt"
"github.com/dpwgc/go-filesort"
"time"
)
type Log struct {
Id int
}
func main() {
id := 0
// 使用 Bulk 函数新建一个排序流程
bulk := filesort.Bulk(Log{})
// 使用 Source、Target、OrderBy 函数设置输入输出及排序规则
bulk.Source(func() ([]Log, error) {
// 输入源:输入12w个ID,从1到120000
if id >= 120000 {
// 终止输入
return nil, nil
}
id++
return []Log{{
Id: id,
}}, nil
}).Target(func(row Log) bool {
// 输出目标:打印排序结果
fmt.Println(row.Id)
return true
}).OrderBy(func(left Log, right Log) bool {
// 排序规则:按ID大小倒序
return left.Id > right.Id
}).Limit(10) // 只输出结果中的前10个
fmt.Println(time.Now(), "-- start")
// 开始排序,在 ./temp 目录下存储临时数据,运行时会在该目录下新建一个临时的 boltdb 数据库,每个数据块对应一个 key,每个 key 至多存储1w行记录
// 如果需要排序的数据总量没到1w,会直接在内存中排序,不走文件排序逻辑
err := bulk.Run("./temp", 10000)
if err != nil {
panic(err)
}
fmt.Println(time.Now(), "-- end")
}
- 其他运行方式
// 在 ./temp 目录下以文件形式存储临时数据
bulk.RunFile("./temp", 10000)
// 自定义临时文件存储方式,可参考下文的'自定义存储'
bulk.RunStore(myStore, 10000)
- Bulk:新建一个排序流程,传入一个泛型来确认排序对象类型。
- Source:设置一个输入源函数,程序运行时会一直尝试调用这个函数,以此来持续获取数据,直到这个函数第1个返回值为 nil,如果这个函数第2个 error 返回值不为 nil,则直接终止排序流程并报错。
- Target:设置一个输出目标函数,通过这个函数来按顺序逐个接收排序结果,如果想提前终止接收,可以令这个函数返回 false。
- OrderBy:设置排序规则,例如 return left.id > right.id 是倒序,return left.id < right.id 是升序。
- Limit:返回结果分页设置,与 MySQL 的 limit 功能相同,limit 10 或者 limit 0,10。
- Run:指定一个本地文件目录(底层使用 boltdb 存储)和分块大小,运行这个排序流程,每个流程只能执行一次 Run。
- RunFile:指定一个本地文件目录(底层使用文件存储)和分块大小,运行这个排序流程。
- RunStore:指定一个自定义存储实现和分块大小,运行这个排序流程。
package store
type Store interface {
// Write 写入数据块,rows 最大长度取决于 blockSize 设置,返回存储路径和异常值
Write(rows []string) (key string, err error)
// Read 读取指定数据块,返回数据和异常值
Read(key string) (rows []string, err error)
// Clear 清除指定数据块
Clear(keys []string)
}