golang通用泛型切片、映射、集合和迭代器工具插件库go-generics的使用

Go-generics - Go语言的通用泛型切片、映射、集合和迭代器工具

简介

go-generics是一个类型安全的通用工具库,为Go语言提供了切片、集合和goroutine模式的实用功能。

兼容性说明

这是该库的第4版,适用于Go 1.23版本。

切片(slices)包

slices包在三个方面很有用:

  1. 封装了难以记忆的Go惯用法,用于在切片中间插入和删除元素
  2. 添加了使用负整数从切片右端索引的能力
  3. 包含MapFilter等函数,用于通过回调处理切片元素

示例代码

package main

import (
	"fmt"
	"github.com/bobg/go-generics/v4/slices"
)

func main() {
	// 创建切片
	s := []int{1, 2, 3, 4, 5}

	// 使用负索引获取最后一个元素
	last := slices.Get(s, -1)
	fmt.Println("Last element:", last) // 输出: 5

	// 在索引2处插入元素
	s = slices.Insert(s, 2, 6, 7)
	fmt.Println("After insert:", s) // 输出: [1 2 6 7 3 4 5]

	// 删除索引-2的元素(倒数第二个)
	s = slices.Delete(s, -2)
	fmt.Println("After delete:", s) // 输出: [1 2 6 7 3 5]

	// 使用Map函数处理切片
	doubled := slices.Map(s, func(x int) int { return x * 2 })
	fmt.Println("Doubled:", doubled) // 输出: [2 4 12 14 6 10]

	// 使用Filter函数过滤切片
	evens := slices.Filter(s, func(x int) bool { return x%2 == 0 })
	fmt.Println("Even numbers:", evens) // 输出: [2 6]
}

集合(set)包

set包实现了常见的集合操作函数:IntersectUnionDiff等,以及用于添加和删除项、检查项是否存在和迭代项的成员函数。

示例代码

package main

import (
	"fmt"
	"github.com/bobg/go-generics/v4/set"
)

func main() {
	// 创建集合
	s1 := set.New[int]()
	s1.Add(1, 2, 3)

	s2 := set.New[int]()
	s2.Add(2, 3, 4)

	// 并集
	union := set.Union(s1, s2)
	fmt.Println("Union:", union) // 输出: {1, 2, 3, 4}

	// 交集
	intersect := set.Intersect(s1, s2)
	fmt.Println("Intersection:", intersect) // 输出: {2, 3}

	// 差集
	diff := set.Diff(s1, s2)
	fmt.Println("Difference (s1 - s2):", diff) // 输出: {1}

	// 检查元素是否存在
	fmt.Println("Contains 2:", s1.Contains(2)) // 输出: true
	fmt.Println("Contains 5:", s1.Contains(5)) // 输出: false

	// 删除元素
	s1.Remove(2)
	fmt.Println("After remove:", s1) // 输出: {1, 3}
}

并行(parallel)包

parallel包包含用于协调并行工作者的函数:

示例代码

package main

import (
	"fmt"
	"github.com/bobg/go-generics/v4/parallel"
	"sync"
)

func main() {
	// Consumers示例
	var wg sync.WaitGroup
	wg.Add(1)
	
	// 创建3个消费者
	consume := parallel.Consumers[int](3, func(i int) {
		defer wg.Done()
		fmt.Printf("Worker %d received: %d\n", i, i*10)
	})
	
	// 发送数据给消费者
	for i := 1; i <= 3; i++ {
		consume(i)
	}
	
	wg.Wait()

	// Values示例
	results := parallel.Values(3, func(i int) string {
		return fmt.Sprintf("result-%d", i+1)
	})
	fmt.Println("Results:", results) // 输出: [result-1 result-2 result-3]

	// Protect示例
	protected := parallel.Protect(42)
	protected.With(func(val *int) {
		*val += 10
		fmt.Println("Protected value:", *val) // 输出: 52
	})
}

总结

go-generics库为Go语言提供了强大的泛型工具,包括:

  • 增强的切片操作
  • 集合操作
  • 并行处理模式

这些工具可以帮助开发者编写更简洁、更安全的代码,特别是在处理集合和并发场景时。


更多关于golang通用泛型切片、映射、集合和迭代器工具插件库go-generics的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang通用泛型切片、映射、集合和迭代器工具插件库go-generics的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


go-generics 库使用指南

go-generics 是一个为 Go 1.18+ 泛型设计的通用工具库,提供了泛型切片、映射、集合和迭代器等实用功能。下面我将详细介绍其主要功能和使用方法。

安装

go get github.com/JustinTimperio/go-generics

核心功能

1. 切片操作 (Slices)

import "github.com/JustinTimperio/go-generics/slices"

func main() {
    // 创建切片
    s := slices.New[int](1, 2, 3, 4, 5)
    
    // 过滤
    even := slices.Filter(s, func(x int) bool { return x%2 == 0 })
    
    // 映射转换
    doubled := slices.Map(s, func(x int) int { return x * 2 })
    
    // 归约
    sum := slices.Reduce(s, 0, func(acc, x int) int { return acc + x })
    
    // 包含检查
    contains := slices.Contains(s, 3)
    
    // 去重
    unique := slices.Unique([]int{1, 2, 2, 3, 3, 3})
}

2. 映射操作 (Maps)

import "github.com/JustinTimperio/go-generics/maps"

func main() {
    m := map[string]int{"a": 1, "b": 2, "c": 3}
    
    // 获取所有键
    keys := maps.Keys(m)
    
    // 获取所有值
    values := maps.Values(m)
    
    // 映射转换
    doubled := maps.MapValues(m, func(x int) int { return x * 2 })
    
    // 过滤
    filtered := maps.Filter(m, func(k string, v int) bool { return v > 1 })
}

3. 集合操作 (Sets)

import "github.com/JustinTimperio/go-generics/set"

func main() {
    // 创建集合
    s := set.New[int]()
    s.Add(1, 2, 3)
    
    // 检查元素
    exists := s.Contains(2)
    
    // 删除元素
    s.Remove(2)
    
    // 集合运算
    s2 := set.New[int](3, 4, 5)
    union := s.Union(s2)      // 并集
    intersect := s.Intersect(s2) // 交集
    diff := s.Difference(s2)  // 差集
}

4. 迭代器 (Iterators)

import "github.com/JustinTimperio/go-generics/iter"

func main() {
    // 从切片创建迭代器
    it := iter.FromSlice([]int{1, 2, 3, 4, 5})
    
    // 过滤偶数
    it = iter.Filter(it, func(x int) bool { return x%2 == 0 })
    
    // 映射转换
    it = iter.Map(it, func(x int) int { return x * 2 })
    
    // 收集结果
    result := iter.Collect(it)
    
    // 直接迭代
    it = iter.FromSlice([]string{"a", "b", "c"})
    for item, ok := it.Next(); ok; item, ok = it.Next() {
        fmt.Println(item)
    }
}

5. 其他实用工具

import "github.com/JustinTimperio/go-generics"

func main() {
    // 指针操作
    x := 10
    ptr := generics.Ptr(x)
    deref := generics.Deref(ptr)
    
    // 元组
    pair := generics.NewPair("key", 123)
    key := pair.First
    value := pair.Second
    
    // 可选值
    maybe := generics.Some(42)
    if val, ok := maybe.Get(); ok {
        fmt.Println("Got value:", val)
    }
    
    maybe = generics.None[int]()
}

性能考虑

go-generics 在设计时考虑了性能因素:

  1. 尽量减少内存分配
  2. 使用内联优化
  3. 避免不必要的接口转换

但对于性能关键路径,建议进行基准测试比较。

最佳实践

  1. 对于简单操作,直接使用原生切片/映射可能更高效
  2. 对于复杂的数据处理链,使用迭代器模式可以提高可读性
  3. 集合操作适合需要频繁成员检查的场景
  4. 使用 go:generate 为特定类型生成优化代码(如果需要)

总结

go-generics 提供了丰富的泛型工具,可以大大简化 Go 中的通用数据操作。它特别适合:

  • 数据处理流水线
  • 复杂集合操作
  • 需要类型安全的数据结构
  • 函数式编程风格的代码

通过合理使用这些工具,可以编写出更简洁、更易维护的 Go 代码。

回到顶部