我是靠谱客的博主 热心网友,这篇文章主要介绍golang泛型的一些经典使用场景和实例,现在分享给大家,希望可以做个参考。

Go 泛型(Generics)在 1.18 版本正式引入后,为开发者提供了更强大的类型抽象能力。以下是 Go 泛型的 经典使用场景实用示例,涵盖数据结构、算法、工具函数等常见需求。

1. 泛型数据结构

场景:实现类型安全的容器(栈、队列、链表等)

示例:泛型栈(Stack)

type Stack[T any] struct {
    items []T
}

func (s *Stack[T]) Push(item T) {
    s.items = append(s.items, item)
}

func (s *Stack[T]) Pop() T {
    if len(s.items) == 0 {
        panic("stack is empty")
    }
    item := s.items[len(s.items)-1]
    s.items = s.items[:len(s.items)-1]
    return item
}

// 使用
intStack := Stack[int]{}
intStack.Push(1)
intStack.Push(2)
fmt.Println(intStack.Pop()) // 输出: 2

stringStack := Stack[string]{}
stringStack.Push("hello")
stringStack.Push("world")

2. 泛型算法

场景:编写可复用的算法逻辑(排序、查找、比较等)

示例:泛型快速排序

func QuickSort[T comparable](arr []T, less func(a, b T) bool) []T {
    if len(arr) <= 1 {
        return arr
    }
    pivot := arr[0]
    var left, right []T
    for _, v := range arr[1:] {
        if less(v, pivot) {
            left = append(left, v)
        } else {
            right = append(right, v)
        }
    }
    left = QuickSort(left, less)
    right = QuickSort(right, less)
    return append(append(left, pivot), right...)
}

// 使用
numbers := []int{3, 1, 4, 1, 5, 9}
sorted := QuickSort(numbers, func(a, b int) bool { return a < b })

words := []string{"banana", "apple", "cherry"}
sortedWords := QuickSort(words, func(a, b string) bool { return a < b })


3. 工具函数

场景:避免为不同类型重复编写相似函数

示例:泛型 Map / Filter / Reduce

// Map:对切片中的每个元素执行函数
func Map[T any, U any](arr []T, f func(T) U) []U {
    result := make([]U, len(arr))
    for i, v := range arr {
        result[i] = f(v)
    }
    return result
}

// 使用
numbers := []int{1, 2, 3}
doubled := Map(numbers, func(x int) int { return x * 2 }) // [2, 4, 6]

names := []string{"alice", "bob"}
uppercased := Map(names, func(s string) string { return strings.ToUpper(s) }) // ["ALICE", "BOB"]


4. 类型约束与组合

场景:限制泛型类型范围(如只允许数字类型)

示例:数值类型求和

type Number interface {
    ~int | ~float64 | ~float32 | ~int64 // 支持所有数值类型
}

func Sum[T Number](nums []T) T {
    var total T
    for _, v := range nums {
        total += v
    }
    return total
}

// 使用
ints := []int{1, 2, 3}
floats := []float64{1.1, 2.2, 3.3}
fmt.Println(Sum(ints))    // 6
fmt.Println(Sum(floats))  // 6.6


5. 泛型与接口结合

场景:对实现了特定接口的类型进行泛型操作

示例:调用 String() 方法的泛型函数

type Stringer interface {
    String() string
}

func PrintString[T Stringer](v T) {
    fmt.Println(v.String())
}

// 自定义类型实现 Stringer
type MyInt int
func (m MyInt) String() string { return fmt.Sprintf("MyInt(%d)", m) }

// 使用
var x MyInt = 42
PrintString(x) // 输出: MyInt(42)


6. 避免 interface{} 和类型断言

场景:替代旧代码中的 interface{},提高类型安全性

示例:类型安全的缓存库

type Cache[K comparable, V any] struct {
    data map[K]V
}

func NewCache[K comparable, V any]() *Cache[K, V] {
    return &Cache[K, V]{data: make(map[K]V)}
}

func (c *Cache[K, V]) Set(key K, value V) {
    c.data[key] = value
}

func (c *Cache[K, V]) Get(key K) (V, bool) {
    v, ok := c.data[key]
    return v, ok
}

// 使用
cache := NewCache[string, int]()
cache.Set("age", 30)
value, exists := cache.Get("age") // value 是 int 类型,无需类型断言


7. 泛型与并发

场景:类型安全的并发模式(如 Worker Pool)

示例:泛型任务处理器

go


func ProcessInParallel[T any](tasks []T, worker func(T)) {
    var wg sync.WaitGroup
    for _, task := range tasks {
        wg.Add(1)
        go func(t T) {
            defer wg.Done()
            worker(t)
        }(task)
    }
    wg.Wait()
}

// 使用
tasks := []int{1, 2, 3, 4, 5}
ProcessInParallel(tasks, func(x int) {
    fmt.Println(x * x) // 并发处理每个任务
})

总结:Go 泛型的适用场景


场景传统方案的问题泛型的优势
数据结构需为每种类型重复实现一套代码支持所有类型
算法复用使用 interface{} + 断言编译时类型安全
工具函数需写多个相似函数逻辑抽象一次,多类型复用
类型约束运行时检查类型编译时限制类型范围
性能敏感代码接口调用有动态分发开销静态展开,无运行时开销

泛型不是万能的,但在上述场景中能显著提升代码的 安全性复用性性能


最后

以上就是热心网友最近收集整理的关于golang泛型的一些经典使用场景和实例的全部内容,更多相关golang泛型内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(370)

评论列表共有 0 条评论

立即
投稿
返回
顶部