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.65. 泛型与接口结合
场景:对实现了特定接口的类型进行泛型操作
示例:调用 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泛型内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复