XArray Guide - zhoudm1743/go-util GitHub Wiki
XArray 是 Go-Util 的核心数组处理工具,基于 Go 泛型设计,提供函数式编程风格的数组操作,让数据处理变得简单而优雅。
🚀 特性亮点
- 🧩 泛型支持: 完整的类型安全,编译时错误检查
- 🔄 函数式编程: Map、Filter、Reduce 等高阶函数
- 🔗 链式调用: 流畅的方法链,提高代码可读性
- ⚡ 高性能: 原地操作和批量处理优化
- 📊 丰富功能: 涵盖所有常见数组操作场景
- 🔧 易扩展: 支持自定义比较和转换函数
📦 基础用法
创建 XArray 对象
import util "github.com/zhoudm1743/go-util"
// 从元素创建
arr := util.Arrays(1, 2, 3, 4, 5) // XArray[int]
strings := util.Arrays("a", "b", "c") // XArray[string]
// 从切片创建
slice := []int{1, 2, 3, 4, 5}
arr2 := util.ArraysFromSlice(slice)
// 创建指定类型的数组
mixed := util.NewArray[interface{}]()
mixed.Append(1, "hello", 3.14, true)
// 创建预分配容量的数组
largeArr := util.NewArrayWithCapacity[int](1000)
// 空数组
empty := util.NewArray[string]()
基础信息获取
arr := util.Arrays(1, 2, 3, 4, 5)
// 长度和容量
fmt.Println(arr.Len()) // 5
fmt.Println(arr.Cap()) // 5 (或更大)
// 状态检查
fmt.Println(arr.IsEmpty()) // false
fmt.Println(arr.IsNotEmpty()) // true
// 转换为切片
slice := arr.ToSlice() // []int{1, 2, 3, 4, 5}
// 获取底层数据
data := arr.Data() // []int{1, 2, 3, 4, 5}
📝 元素操作
添加元素
arr := util.NewArray[int]()
// 单个添加
arr.Append(1) // [1]
arr.Prepend(0) // [0, 1]
arr.Insert(1, 999) // [0, 999, 1]
// 批量添加
arr.AppendSlice([]int{2, 3, 4}) // [0, 999, 1, 2, 3, 4]
arr.PrependSlice([]int{-2, -1}) // [-2, -1, 0, 999, 1, 2, 3, 4]
// 链式添加
result := util.NewArray[string]().
Append("hello").
Append("world").
Prepend("hi") // ["hi", "hello", "world"]
删除元素
arr := util.Arrays(1, 2, 3, 4, 5, 3, 6)
// 按索引删除
arr.RemoveAt(0) // [2, 3, 4, 5, 3, 6]
arr.RemoveRange(1, 3) // [2, 5, 3, 6]
// 按值删除
arr.Remove(3) // [2, 5, 6] (删除第一个3)
arr.RemoveAll(3) // [2, 5, 6] (删除所有3)
// 删除重复项
arr2 := util.Arrays(1, 2, 2, 3, 3, 3, 4)
unique := arr2.Distinct() // [1, 2, 3, 4]
// 清空数组
arr.Clear() // []
访问元素
arr := util.Arrays("apple", "banana", "cherry", "date")
// 索引访问
first := arr.Get(0) // "apple"
last := arr.Get(-1) // "date" (支持负索引)
// 安全访问
value, ok := arr.SafeGet(10) // "", false (越界返回零值)
valueOrDefault := arr.GetOr(10, "default") // "default"
// 查找元素
index := arr.IndexOf("banana") // 1
lastIndex := arr.LastIndexOf("banana") // 1
found := arr.Contains("cherry") // true
// 范围访问
subArray := arr.Slice(1, 3) // ["banana", "cherry"]
head := arr.Head(2) // ["apple", "banana"]
tail := arr.Tail(2) // ["cherry", "date"]
🔄 函数式编程
Map 转换
numbers := util.Arrays(1, 2, 3, 4, 5)
// 基础转换
squares := numbers.Map(func(n int) int {
return n * n
}) // [1, 4, 9, 16, 25]
// 类型转换
strings := numbers.Map(func(n int) string {
return fmt.Sprintf("num_%d", n)
}) // ["num_1", "num_2", "num_3", "num_4", "num_5"]
// 带索引的转换
indexed := numbers.MapWithIndex(func(i, n int) string {
return fmt.Sprintf("%d:%d", i, n)
}) // ["0:1", "1:2", "2:3", "3:4", "4:5"]
// 原地转换 (性能更好)
numbers.MapInPlace(func(n int) int {
return n * 2
}) // [2, 4, 6, 8, 10]
Filter 过滤
numbers := util.Arrays(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 基础过滤
evens := numbers.Filter(func(n int) bool {
return n%2 == 0
}) // [2, 4, 6, 8, 10]
// 带索引的过滤
filteredWithIndex := numbers.FilterWithIndex(func(i, n int) bool {
return i%2 == 0 && n > 3 // 偶数索引且值大于3
}) // [5, 7, 9]
// 原地过滤
numbers.FilterInPlace(func(n int) bool {
return n <= 5
}) // [1, 2, 3, 4, 5]
// 拒绝过滤 (排除满足条件的)
odds := util.Arrays(1, 2, 3, 4, 5).Reject(func(n int) bool {
return n%2 == 0
}) // [1, 3, 5]
Reduce 聚合
numbers := util.Arrays(1, 2, 3, 4, 5)
// 基础聚合
sum := numbers.Reduce(func(acc, curr int) int {
return acc + curr
}, 0) // 15
product := numbers.Reduce(func(acc, curr int) int {
return acc * curr
}, 1) // 120
// 字符串连接
words := util.Arrays("hello", "world", "go")
sentence := words.Reduce(func(acc, curr string) string {
if acc == "" {
return curr
}
return acc + " " + curr
}, "") // "hello world go"
// 查找最大值
max := numbers.Reduce(func(acc, curr int) int {
if curr > acc {
return curr
}
return acc
}, numbers.Get(0)) // 5
ForEach 遍历
fruits := util.Arrays("apple", "banana", "cherry")
// 基础遍历
fruits.ForEach(func(i int, fruit string) bool {
fmt.Printf("%d: %s\n", i, fruit)
return true // 继续遍历
})
// 条件中断
fruits.ForEach(func(i int, fruit string) bool {
fmt.Printf("%s\n", fruit)
return fruit != "banana" // 遇到banana时停止
})
// 简单遍历 (无索引)
fruits.Each(func(fruit string) {
fmt.Println(fruit)
})
🔍 查找和匹配
查找操作
numbers := util.Arrays(1, 2, 3, 4, 5, 6)
// 查找第一个匹配
first, found := numbers.Find(func(n int) bool {
return n > 3
}) // 4, true
// 查找最后一个匹配
last, found := numbers.FindLast(func(n int) bool {
return n%2 == 0
}) // 6, true
// 查找索引
index := numbers.FindIndex(func(n int) bool {
return n > 3
}) // 3
// 查找所有匹配
allEvens := numbers.FindAll(func(n int) bool {
return n%2 == 0
}) // [2, 4, 6]
条件检查
numbers := util.Arrays(1, 2, 3, 4, 5)
// 全部满足
allPositive := numbers.All(func(n int) bool {
return n > 0
}) // true
// 任意满足
anyEven := numbers.Any(func(n int) bool {
return n%2 == 0
}) // true
// 无任何满足
noneNegative := numbers.None(func(n int) bool {
return n < 0
}) // true
// 计数
evenCount := numbers.Count(func(n int) bool {
return n%2 == 0
}) // 2
📊 排序和分组
排序操作
// 基础排序 (需要实现 Ordered 约束)
numbers := util.Arrays(5, 2, 8, 1, 9, 3)
sorted := numbers.Sort() // [1, 2, 3, 5, 8, 9]
reversed := numbers.SortDesc() // [9, 8, 5, 3, 2, 1]
// 原地排序
numbers.SortInPlace() // [1, 2, 3, 5, 8, 9]
numbers.ReverseInPlace() // [9, 8, 5, 3, 2, 1]
// 自定义排序
users := util.Arrays(
User{Name: "Alice", Age: 30},
User{Name: "Bob", Age: 25},
User{Name: "Charlie", Age: 35},
)
// 按年龄排序
sortedByAge := users.SortBy(func(u User) int {
return u.Age
})
// 自定义比较函数
sortedByName := users.SortWith(func(a, b User) bool {
return a.Name < b.Name
})
// 检查是否已排序
isSorted := numbers.IsSorted() // true
分组操作
numbers := util.Arrays(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 按条件分组
grouped := numbers.GroupBy(func(n int) string {
if n%2 == 0 {
return "even"
}
return "odd"
}) // map[string][]int{"even": [2,4,6,8,10], "odd": [1,3,5,7,9]}
// 分块处理
chunks := numbers.Chunk(3) // [1,2,3], [4,5,6], [7,8,9], [10](/zhoudm1743/go-util/wiki/1,2,3],-[4,5,6],-[7,8,9],-[10)
// 分区
evens, odds := numbers.Partition(func(n int) bool {
return n%2 == 0
}) // evens: [2,4,6,8,10], odds: [1,3,5,7,9]
🔗 数组组合
连接操作
arr1 := util.Arrays(1, 2, 3)
arr2 := util.Arrays(4, 5, 6)
arr3 := util.Arrays(7, 8, 9)
// 连接数组
combined := arr1.Concat(arr2) // [1, 2, 3, 4, 5, 6]
// 多数组连接
multiCombined := arr1.ConcatMultiple(arr2, arr3) // [1,2,3,4,5,6,7,8,9]
// 原地连接
arr1.ConcatInPlace(arr2) // arr1 变为 [1,2,3,4,5,6]
集合操作
set1 := util.Arrays(1, 2, 3, 4, 5)
set2 := util.Arrays(3, 4, 5, 6, 7)
// 交集
intersection := set1.Intersect(set2) // [3, 4, 5]
// 并集
union := set1.Union(set2) // [1, 2, 3, 4, 5, 6, 7]
// 差集
difference := set1.Difference(set2) // [1, 2]
// 对称差集
symmetricDiff := set1.SymmetricDifference(set2) // [1, 2, 6, 7]
// 子集检查
isSubset := util.Arrays(1, 2).IsSubsetOf(set1) // true
🔄 数组变换
形状变换
numbers := util.Arrays(1, 2, 3, 4, 5, 6)
// 反转
reversed := numbers.Reverse() // [6, 5, 4, 3, 2, 1]
// 洗牌
shuffled := numbers.Shuffle() // [3, 1, 6, 2, 5, 4] (随机)
// 旋转
rotated := numbers.Rotate(2) // [3, 4, 5, 6, 1, 2]
rotatedLeft := numbers.RotateLeft(2) // [5, 6, 1, 2, 3, 4]
// 填充
filled := util.NewArray[int]().Fill(0, 5) // [0, 0, 0, 0, 0]
// 重复
repeated := util.Arrays(1, 2).Repeat(3) // [1, 2, 1, 2, 1, 2]
抽样和选择
numbers := util.Arrays(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 取前N个
first3 := numbers.Take(3) // [1, 2, 3]
// 跳过前N个
skip3 := numbers.Skip(3) // [4, 5, 6, 7, 8, 9, 10]
// 取满足条件的前N个
takeWhile := numbers.TakeWhile(func(n int) bool {
return n < 5
}) // [1, 2, 3, 4]
// 跳过满足条件的元素
skipWhile := numbers.SkipWhile(func(n int) bool {
return n < 5
}) // [5, 6, 7, 8, 9, 10]
// 随机抽样
sample := numbers.Sample(3) // 随机选择3个元素
📈 统计和聚合
数值统计
numbers := util.Arrays(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 基础统计
sum := numbers.Sum() // 55 (需要数值类型)
avg := numbers.Average() // 5.5
min := numbers.Min() // 1
max := numbers.Max() // 10
// 中位数和众数
median := numbers.Median() // 5.5
mode := numbers.Mode() // 可能返回多个值
// 方差和标准差
variance := numbers.Variance() // 8.25
stdDev := numbers.StandardDeviation() // 2.87
// 自定义聚合
maxLength := util.Arrays("a", "bb", "ccc", "d").
MaxBy(func(s string) int {
return len(s)
}) // "ccc"
频率分析
grades := util.Arrays("A", "B", "A", "C", "B", "A", "D")
// 频率统计
frequency := grades.Frequency() // map[string]int{"A":3, "B":2, "C":1, "D":1}
// 最频繁的元素
mostFrequent := grades.MostFrequent() // "A"
// 按频率排序
sortedByFreq := grades.SortByFrequency() // ["A", "A", "A", "B", "B", "C", "D"]
🔧 高级功能
自定义比较和相等
type Person struct {
Name string
Age int
}
people := util.Arrays(
Person{"Alice", 30},
Person{"Bob", 25},
Person{"Alice", 30},
)
// 自定义相等比较
unique := people.DistinctBy(func(p Person) string {
return p.Name // 按姓名去重
})
// 自定义比较函数
sorted := people.SortWith(func(a, b Person) bool {
if a.Age != b.Age {
return a.Age < b.Age
}
return a.Name < b.Name // 年龄相同时按姓名排序
})
并行处理
largeNumbers := util.NewArray[int]()
for i := 0; i < 1000000; i++ {
largeNumbers.Append(i)
}
// 并行映射
results := largeNumbers.ParallelMap(func(n int) int {
return n * n // 计算平方
}, 4) // 使用4个goroutine
// 并行过滤
filtered := largeNumbers.ParallelFilter(func(n int) bool {
return n%2 == 0
}, 4) // 使用4个goroutine
// 并行聚合
sum := largeNumbers.ParallelReduce(func(acc, curr int) int {
return acc + curr
}, 0, 4) // 使用4个goroutine
管道操作
// 复杂的数据处理管道
result := util.Arrays(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).
Filter(func(n int) bool { return n%2 == 0 }). // 过滤偶数
Map(func(n int) int { return n * 3 }). // 乘以3
Filter(func(n int) bool { return n > 10 }). // 大于10
Take(3). // 取前3个
Sort(). // 排序
ToSlice() // 转为切片
fmt.Println(result) // [12, 18, 24]
🚀 性能优化
原地操作
numbers := util.Arrays(5, 2, 8, 1, 9, 3)
// ✅ 原地操作 (更高效)
numbers.SortInPlace() // 原地排序
numbers.ReverseInPlace() // 原地反转
numbers.FilterInPlace(func(n int) bool {
return n > 3
}) // 原地过滤
// ❌ 创建新数组 (内存开销大)
sorted := numbers.Sort()
reversed := numbers.Reverse()
filtered := numbers.Filter(func(n int) bool {
return n > 3
})
预分配容量
// ✅ 预分配容量
expectedSize := 10000
arr := util.NewArrayWithCapacity[int](expectedSize)
for i := 0; i < expectedSize; i++ {
arr.Append(i) // 避免多次扩容
}
// ✅ 批量操作
data := make([]int, 10000)
for i := range data {
data[i] = i
}
arr2 := util.ArraysFromSlice(data) // 一次性创建
并发处理
// 大数据集并发处理
func ProcessLargeArray(data *util.XArray[int]) *util.XArray[int] {
workerCount := runtime.NumCPU()
return data.
ParallelFilter(heavyFilterCondition, workerCount).
ParallelMap(expensiveTransform, workerCount).
ParallelSort(workerCount)
}
🔍 实际应用场景
数据清洗
// 用户数据清洗
func CleanUserData(users []User) []User {
return util.ArraysFromSlice(users).
Filter(func(u User) bool {
return u.Email != "" && u.Age > 0 // 过滤无效数据
}).
DistinctBy(func(u User) string {
return u.Email // 按邮箱去重
}).
SortBy(func(u User) string {
return u.Name // 按姓名排序
}).
ToSlice()
}
// CSV数据处理
func ProcessCSVData(records [][]string) []map[string]string {
if len(records) == 0 {
return nil
}
headers := records[0]
data := records[1:]
return util.ArraysFromSlice(data).
Filter(func(record []string) bool {
return len(record) == len(headers) // 过滤格式错误的行
}).
Map(func(record []string) map[string]string {
result := make(map[string]string)
for i, value := range record {
result[headers[i]] = strings.TrimSpace(value)
}
return result
}).
ToSlice()
}
数据分析
// 销售数据分析
type Sale struct {
Product string
Amount float64
Date time.Time
Category string
}
func AnalyzeSales(sales []Sale) map[string]float64 {
return util.ArraysFromSlice(sales).
Filter(func(s Sale) bool {
return s.Amount > 0 // 过滤无效销售
}).
GroupBy(func(s Sale) string {
return s.Category // 按类别分组
}).
MapValues(func(salesInCategory []Sale) float64 {
return util.ArraysFromSlice(salesInCategory).
Map(func(s Sale) float64 { return s.Amount }).
Sum() // 计算每个类别的总销售额
})
}
// 学生成绩统计
func AnalyzeGrades(students []Student) GradeStats {
scores := util.ArraysFromSlice(students).
Map(func(s Student) float64 { return s.Score }).
Filter(func(score float64) bool { return score >= 0 })
return GradeStats{
Average: scores.Average(),
Median: scores.Median(),
Min: scores.Min(),
Max: scores.Max(),
PassRate: scores.Count(func(s float64) bool { return s >= 60 }) / float64(scores.Len()),
}
}
API 响应处理
// API响应数据转换
func TransformAPIResponse(response APIResponse) []DisplayItem {
return util.ArraysFromSlice(response.Items).
Filter(func(item APIItem) bool {
return item.Status == "active" // 只显示活跃项目
}).
Map(func(item APIItem) DisplayItem {
return DisplayItem{
ID: item.ID,
Title: strings.Title(item.Name),
Description: util.Str(item.Description).Truncate(100).String(),
Tags: item.Tags,
}
}).
SortBy(func(item DisplayItem) string {
return item.Title // 按标题排序
}).
Take(20). // 限制返回数量
ToSlice()
}
// 批量数据验证
func ValidateBatchData(data []UserInput) ([]ValidUser, []ValidationError) {
results := util.ArraysFromSlice(data).
MapWithIndex(func(i int, input UserInput) ValidationResult {
if err := validateUser(input); err != nil {
return ValidationResult{Index: i, Error: err}
}
return ValidationResult{Index: i, User: transformToUser(input)}
})
errors := results.
Filter(func(r ValidationResult) bool { return r.Error != nil }).
Map(func(r ValidationResult) ValidationError {
return ValidationError{Index: r.Index, Message: r.Error.Error()}
}).ToSlice()
users := results.
Filter(func(r ValidationResult) bool { return r.Error == nil }).
Map(func(r ValidationResult) ValidUser { return r.User }).
ToSlice()
return users, errors
}
📊 性能基准
基准测试结果
操作类型 元素数量 性能指标
基础操作 (Append/Get) 10万 微秒级
Map 转换 10万 毫秒级
Filter 过滤 10万 毫秒级
Sort 排序 10万 20-50ms
Reduce 聚合 100万 100ms
并行操作 (4核) 100万 25-30ms
内存使用优化
// 基准测试示例
func BenchmarkArrayOperations(b *testing.B) {
data := make([]int, 10000)
for i := range data {
data[i] = rand.Intn(1000)
}
arr := util.ArraysFromSlice(data)
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := arr.
Filter(func(n int) bool { return n%2 == 0 }).
Map(func(n int) int { return n * 2 }).
Take(100).
ToSlice()
_ = result
}
}
// 结果示例:
// BenchmarkArrayOperations-8 1000 1.2ms/op 156KB/op 15 allocs/op
🎯 最佳实践
1. 性能优化
// ✅ 使用原地操作
arr.FilterInPlace(condition)
arr.SortInPlace()
// ✅ 预分配容量
arr := util.NewArrayWithCapacity[int](expectedSize)
// ✅ 并行处理大数据
arr.ParallelMap(transform, runtime.NumCPU())
// ❌ 避免频繁的小数组操作
for i := 0; i < 1000; i++ {
arr := util.Arrays(i) // 每次都创建新数组
}
2. 内存管理
// ✅ 及时释放大数组
defer func() { largeArray = nil }()
// ✅ 使用流式处理
result := processInChunks(data, 1000)
// ✅ 选择合适的操作
if needNewArray {
filtered := arr.Filter(condition) // 创建新数组
} else {
arr.FilterInPlace(condition) // 原地修改
}
3. 可读性优化
// ✅ 清晰的函数式管道
processedData := util.ArraysFromSlice(rawData).
Filter(isValid). // 步骤1:验证数据
Map(transform). // 步骤2:转换格式
GroupBy(categorize). // 步骤3:分组
MapValues(aggregate). // 步骤4:聚合计算
ToMap()
// ✅ 使用有意义的函数名
isActiveUser := func(u User) bool { return u.Status == "active" }
activeUsers := users.Filter(isActiveUser)
🔗 相关资源
💬 获取帮助
如果您在使用 XArray 时遇到问题:
- 🔍 查看FAQ - 常见数组处理问题
- 🐛 报告问题 - Bug反馈
- 💡 功能建议 - 新功能讨论
- 📧 邮件支持 - [email protected]
🎉 现在您已经掌握了 XArray 的强大功能,开始在项目中使用这些优雅的数组操作吧!