This commit is contained in:
2025-08-24 13:01:09 +08:00
parent 61e51ad014
commit f028913eb8
36 changed files with 10420 additions and 70 deletions

View File

@@ -0,0 +1,561 @@
/*
02-generics.go - Go 语言泛型详解
学习目标:
1. 理解泛型的概念和优势
2. 掌握类型参数的定义和使用
3. 学会类型约束的应用
4. 了解泛型函数和泛型类型
5. 掌握泛型的最佳实践
知识点:
- 泛型的基本概念
- 类型参数和类型约束
- 泛型函数和泛型类型
- 内置约束和自定义约束
- 类型推断
- 泛型的实际应用
注意:此示例需要 Go 1.18 或更高版本
*/
package main
import (
"fmt"
"sort"
"strconv"
"strings"
)
func main() {
fmt.Println("=== Go 语言泛型详解 ===\\n")
// 演示泛型的基本概念
demonstrateGenericsBasics()
// 演示泛型函数
demonstrateGenericFunctions()
// 演示泛型类型
demonstrateGenericTypes()
// 演示类型约束
demonstrateTypeConstraints()
// 演示内置约束
demonstrateBuiltinConstraints()
// 演示泛型的实际应用
demonstratePracticalApplications()
// 演示泛型的最佳实践
demonstrateBestPractices()
}
// demonstrateGenericsBasics 演示泛型的基本概念
func demonstrateGenericsBasics() {
fmt.Println("1. 泛型的基本概念:")
// 泛型的基本概念
fmt.Printf(" 泛型的基本概念:\\n")
fmt.Printf(" - 泛型允许编写可重用的代码\\n")
fmt.Printf(" - 类型参数在编译时确定具体类型\\n")
fmt.Printf(" - 提供类型安全的抽象\\n")
fmt.Printf(" - Go 1.18+ 支持泛型\\n")
fmt.Printf(" - 减少代码重复和类型断言\\n")
// 泛型语法
fmt.Printf(" 泛型语法:\\n")
fmt.Printf(" 函数泛型: func Name[T any](param T) T\\n")
fmt.Printf(" 类型泛型: type Name[T any] struct { field T }\\n")
fmt.Printf(" 约束语法: func Name[T Constraint](param T) T\\n")
// 简单泛型函数示例
fmt.Printf(" 简单泛型函数示例:\\n")
// 使用泛型函数
fmt.Printf(" 整数最大值: %d\\n", Max(10, 20))
fmt.Printf(" 浮点数最大值: %.2f\\n", Max(3.14, 2.71))
fmt.Printf(" 字符串最大值: %s\\n", Max("apple", "banana"))
// 类型推断
fmt.Printf(" 类型推断:\\n")
fmt.Printf(" Go 编译器可以自动推断类型参数\\n")
// 显式指定类型参数
result1 := Max[int](5, 8)
fmt.Printf(" 显式指定类型: %d\\n", result1)
// 自动类型推断
result2 := Max(5, 8)
fmt.Printf(" 自动类型推断: %d\\n", result2)
// 泛型的优势
fmt.Printf(" 泛型的优势:\\n")
fmt.Printf(" 1. 类型安全:编译时检查类型\\n")
fmt.Printf(" 2. 代码复用:一套代码支持多种类型\\n")
fmt.Printf(" 3. 性能优化:避免运行时类型断言\\n")
fmt.Printf(" 4. 可读性:减少重复代码\\n")
fmt.Printf(" 5. 维护性:统一的逻辑实现\\n")
fmt.Println()
}
// demonstrateGenericFunctions 演示泛型函数
func demonstrateGenericFunctions() {
fmt.Println("2. 泛型函数:")
// 基本泛型函数
fmt.Printf(" 基本泛型函数:\\n")
// 交换函数
a, b := 10, 20
fmt.Printf(" 交换前: a=%d, b=%d\\n", a, b)
a, b = Swap(a, b)
fmt.Printf(" 交换后: a=%d, b=%d\\n", a, b)
str1, str2 := "hello", "world"
fmt.Printf(" 交换前: str1=%s, str2=%s\\n", str1, str2)
str1, str2 = Swap(str1, str2)
fmt.Printf(" 交换后: str1=%s, str2=%s\\n", str1, str2)
// 查找函数
fmt.Printf(" 查找函数:\\n")
numbers := []int{1, 2, 3, 4, 5}
index := Find(numbers, 3)
fmt.Printf(" 在 %v 中查找 3: 索引 %d\\n", numbers, index)
words := []string{"apple", "banana", "cherry"}
index = Find(words, "banana")
fmt.Printf(" 在 %v 中查找 banana: 索引 %d\\n", words, index)
// 映射函数
fmt.Printf(" 映射函数:\\n")
// 数字平方
squares := Map([]int{1, 2, 3, 4, 5}, func(x int) int {
return x * x
})
fmt.Printf(" 数字平方: %v\\n", squares)
// 字符串长度
lengths := Map([]string{"go", "rust", "python"}, func(s string) int {
return len(s)
})
fmt.Printf(" 字符串长度: %v\\n", lengths)
// 过滤函数
fmt.Printf(" 过滤函数:\\n")
// 过滤偶数
evens := Filter([]int{1, 2, 3, 4, 5, 6}, func(x int) bool {
return x%2 == 0
})
fmt.Printf(" 偶数: %v\\n", evens)
// 过滤长字符串
longWords := Filter([]string{"go", "rust", "python", "javascript"}, func(s string) bool {
return len(s) > 4
})
fmt.Printf(" 长单词: %v\\n", longWords)
// 归约函数
fmt.Printf(" 归约函数:\\n")
// 求和
sum := Reduce([]int{1, 2, 3, 4, 5}, 0, func(acc, x int) int {
return acc + x
})
fmt.Printf(" 数组求和: %d\\n", sum)
// 字符串连接
concat := Reduce([]string{"Hello", " ", "World", "!"}, "", func(acc, s string) string {
return acc + s
})
fmt.Printf(" 字符串连接: %s\\n", concat)
// 多类型参数函数
fmt.Printf(" 多类型参数函数:\\n")
pairs := Zip([]int{1, 2, 3}, []string{"a", "b", "c"})
fmt.Printf(" 配对结果: %v\\n", pairs)
fmt.Println()
}
// demonstrateGenericTypes 演示泛型类型
func demonstrateGenericTypes() {
fmt.Println("3. 泛型类型:")
// 泛型栈
fmt.Printf(" 泛型栈:\\n")
// 整数栈
intStack := NewStack[int]()
intStack.Push(1)
intStack.Push(2)
intStack.Push(3)
fmt.Printf(" 整数栈大小: %d\\n", intStack.Size())
for !intStack.IsEmpty() {
value, _ := intStack.Pop()
fmt.Printf(" 弹出: %d\\n", value)
}
// 字符串栈
strStack := NewStack[string]()
strStack.Push("first")
strStack.Push("second")
strStack.Push("third")
fmt.Printf(" 字符串栈内容:\\n")
for !strStack.IsEmpty() {
value, _ := strStack.Pop()
fmt.Printf(" %s\\n", value)
}
// 泛型队列
fmt.Printf(" 泛型队列:\\n")
queue := NewQueue[string]()
queue.Enqueue("first")
queue.Enqueue("second")
queue.Enqueue("third")
fmt.Printf(" 队列大小: %d\\n", queue.Size())
for !queue.IsEmpty() {
value, _ := queue.Dequeue()
fmt.Printf(" 出队: %s\\n", value)
}
// 泛型映射
fmt.Printf(" 泛型映射:\\n")
cache := NewCache[string, int]()
cache.Set("apple", 5)
cache.Set("banana", 3)
cache.Set("cherry", 8)
if value, ok := cache.Get("apple"); ok {
fmt.Printf(" apple 的值: %d\\n", value)
}
fmt.Printf(" 缓存大小: %d\\n", cache.Size())
fmt.Printf(" 所有键: %v\\n", cache.Keys())
// 泛型链表
fmt.Printf(" 泛型链表:\\n")
list := NewLinkedList[int]()
list.Add(1)
list.Add(2)
list.Add(3)
fmt.Printf(" 链表大小: %d\\n", list.Size())
fmt.Printf(" 链表内容: %v\\n", list.ToSlice())
if list.Contains(2) {
fmt.Printf(" 链表包含 2\\n")
}
list.Remove(2)
fmt.Printf(" 删除 2 后: %v\\n", list.ToSlice())
fmt.Println()
}
// demonstrateTypeConstraints 演示类型约束
func demonstrateTypeConstraints() {
fmt.Println("4. 类型约束:")
// 基本约束
fmt.Printf(" 基本约束:\\n")
fmt.Printf(" any: 任意类型\\n")
fmt.Printf(" comparable: 可比较类型\\n")
// 自定义约束
fmt.Printf(" 自定义约束:\\n")
// 数值类型约束
fmt.Printf(" 数值类型约束:\\n")
fmt.Printf(" 整数求和: %d\\n", Sum([]int{1, 2, 3, 4, 5}))
fmt.Printf(" 浮点数求和: %.2f\\n", Sum([]float64{1.1, 2.2, 3.3}))
// 有序类型约束
fmt.Printf(" 有序类型约束:\\n")
intSlice := []int{3, 1, 4, 1, 5, 9}
fmt.Printf(" 排序前: %v\\n", intSlice)
SortSlice(intSlice)
fmt.Printf(" 排序后: %v\\n", intSlice)
strSlice := []string{"banana", "apple", "cherry"}
fmt.Printf(" 排序前: %v\\n", strSlice)
SortSlice(strSlice)
fmt.Printf(" 排序后: %v\\n", strSlice)
// 字符串化约束
fmt.Printf(" 字符串化约束:\\n")
fmt.Printf(" 整数转字符串: %s\\n", ToString(42))
fmt.Printf(" 浮点数转字符串: %s\\n", ToString(3.14))
fmt.Printf(" 布尔值转字符串: %s\\n", ToString(true))
// 接口约束
fmt.Printf(" 接口约束:\\n")
shapes := []Shape{
Rectangle{Width: 5, Height: 3},
Circle{Radius: 4},
}
totalArea := CalculateTotalArea(shapes)
fmt.Printf(" 总面积: %.2f\\n", totalArea)
// 类型集合约束
fmt.Printf(" 类型集合约束:\\n")
fmt.Printf(" 整数绝对值: %d\\n", Abs(-42))
fmt.Printf(" 浮点数绝对值: %.2f\\n", Abs(-3.14))
fmt.Println()
}
// demonstrateBuiltinConstraints 演示内置约束
func demonstrateBuiltinConstraints() {
fmt.Println("5. 内置约束:")
// comparable 约束
fmt.Printf(" comparable 约束:\\n")
// 可比较类型的相等检查
fmt.Printf(" 整数相等: %t\\n", Equal(5, 5))
fmt.Printf(" 字符串相等: %t\\n", Equal("hello", "hello"))
fmt.Printf(" 布尔值相等: %t\\n", Equal(true, false))
// 可比较类型的去重
duplicateInts := []int{1, 2, 2, 3, 3, 3, 4}
uniqueInts := Unique(duplicateInts)
fmt.Printf(" 整数去重: %v -> %v\\n", duplicateInts, uniqueInts)
duplicateStrs := []string{"a", "b", "b", "c", "c", "c"}
uniqueStrs := Unique(duplicateStrs)
fmt.Printf(" 字符串去重: %v -> %v\\n", duplicateStrs, uniqueStrs)
// any 约束
fmt.Printf(" any 约束:\\n")
// 任意类型的容器
container := NewContainer[any]()
container.Add(42)
container.Add("hello")
container.Add(3.14)
container.Add(true)
fmt.Printf(" 容器大小: %d\\n", container.Size())
fmt.Printf(" 容器内容:\\n")
for i := 0; i < container.Size(); i++ {
item := container.Get(i)
fmt.Printf(" [%d]: %v (%T)\\n", i, item, item)
}
// 类型断言与泛型
fmt.Printf(" 类型断言与泛型:\\n")
values := []any{42, "hello", 3.14, true}
// 提取特定类型
strings := ExtractType[string](values)
fmt.Printf(" 提取字符串: %v\\n", strings)
numbers := ExtractType[int](values)
fmt.Printf(" 提取整数: %v\\n", numbers)
fmt.Println()
}
// demonstratePracticalApplications 演示泛型的实际应用
func demonstratePracticalApplications() {
fmt.Println("6. 泛型的实际应用:")
// 应用1: 泛型数据结构
fmt.Printf(" 应用1 - 泛型数据结构:\\n")
// 优先队列
pq := NewPriorityQueue[int]()
pq.Push(3, 3)
pq.Push(1, 1)
pq.Push(4, 4)
pq.Push(2, 2)
fmt.Printf(" 优先队列出队顺序:\\n")
for !pq.IsEmpty() {
item, priority := pq.Pop()
fmt.Printf(" 项目: %v, 优先级: %d\\n", item, priority)
}
// 应用2: 泛型算法
fmt.Printf(" 应用2 - 泛型算法:\\n")
// 二分查找
sortedInts := []int{1, 3, 5, 7, 9, 11, 13}
index := BinarySearch(sortedInts, 7)
fmt.Printf(" 二分查找 7 在 %v 中的位置: %d\\n", sortedInts, index)
sortedStrs := []string{"apple", "banana", "cherry", "date"}
index = BinarySearch(sortedStrs, "cherry")
fmt.Printf(" 二分查找 cherry 在 %v 中的位置: %d\\n", sortedStrs, index)
// 应用3: 泛型工具函数
fmt.Printf(" 应用3 - 泛型工具函数:\\n")
// 切片操作
original := []int{1, 2, 3, 4, 5}
// 反转
reversed := Reverse(original)
fmt.Printf(" 反转: %v -> %v\\n", original, reversed)
// 分块
chunks := Chunk(original, 2)
fmt.Printf(" 分块(大小2): %v -> %v\\n", original, chunks)
// 去重并排序
unsorted := []int{3, 1, 4, 1, 5, 9, 2, 6, 5}
uniqueSorted := UniqueAndSort(unsorted)
fmt.Printf(" 去重排序: %v -> %v\\n", unsorted, uniqueSorted)
// 应用4: 泛型缓存
fmt.Printf(" 应用4 - 泛型缓存:\\n")
lruCache := NewLRUCache[string, string](3)
lruCache.Put("a", "apple")
lruCache.Put("b", "banana")
lruCache.Put("c", "cherry")
fmt.Printf(" 缓存状态: %v\\n", lruCache.Keys())
// 访问会更新顺序
if value, ok := lruCache.Get("a"); ok {
fmt.Printf(" 获取 a: %s\\n", value)
}
// 添加新项会淘汰最久未使用的
lruCache.Put("d", "date")
fmt.Printf(" 添加 d 后: %v\\n", lruCache.Keys())
// 应用5: 泛型验证器
fmt.Printf(" 应用5 - 泛型验证器:\\n")
validator := NewValidator[User]()
// 添加验证规则
validator.AddRule(\"name\", func(u User) bool {
return len(u.Name) > 0
}, \"姓名不能为空\")
validator.AddRule(\"age\", func(u User) bool {
return u.Age >= 0 && u.Age <= 150
}, \"年龄必须在0-150之间\")
validator.AddRule(\"email\", func(u User) bool {
return strings.Contains(u.Email, \"@\")
}, \"邮箱格式不正确\")
// 验证用户
validUser := User{Name: \"Alice\", Age: 25, Email: \"alice@example.com\"}
invalidUser := User{Name: \"\", Age: -5, Email: \"invalid\"}
if errors := validator.Validate(validUser); len(errors) == 0 {
fmt.Printf(" 有效用户验证通过\\n")
} else {
fmt.Printf(" 有效用户验证失败: %v\\n", errors)
}
if errors := validator.Validate(invalidUser); len(errors) > 0 {
fmt.Printf(" 无效用户验证失败: %v\\n", errors)
}
fmt.Println()
}
// demonstrateBestPractices 演示泛型的最佳实践
func demonstrateBestPractices() {
fmt.Println("7. 泛型的最佳实践:")
// 最佳实践原则
fmt.Printf(" 最佳实践原则:\\n")
fmt.Printf(" 1. 优先使用具体类型必要时才使用泛型\\n")
fmt.Printf(" 2. 使用有意义的类型参数名称\\n")
fmt.Printf(" 3. 合理使用类型约束\\n")
fmt.Printf(" 4. 避免过度泛型化\\n")
fmt.Printf(" 5. 考虑编译时间和代码复杂度\\n")
// 命名约定
fmt.Printf(" 命名约定:\\n")
fmt.Printf(" - T: 通用类型参数\\n")
fmt.Printf(" - K, V: 键值对类型\\n")
fmt.Printf(" - E: 元素类型\\n")
fmt.Printf(" - R: 结果类型\\n")
fmt.Printf(" - 使用描述性名称: TKey, TValue, TElement\\n")
// 约束设计
fmt.Printf(" 约束设计:\\n")
fmt.Printf(" - 使用最小必要约束\\n")
fmt.Printf(" - 优先使用内置约束\\n")
fmt.Printf(" - 自定义约束要有明确语义\\n")
fmt.Printf(" - 避免过于复杂的约束\\n")
// 性能考虑
fmt.Printf(" 性能考虑:\\n")
// 泛型 vs 接口性能对比
fmt.Printf(" 泛型 vs 接口性能对比:\\n")
// 泛型版本
start := time.Now()
genericSum := 0
for i := 0; i < 1000000; i++ {
genericSum = Add(genericSum, 1)
}
genericTime := time.Since(start)
// 接口版本
start = time.Now()
var interfaceSum Addable = IntValue(0)
for i := 0; i < 1000000; i++ {
interfaceSum = interfaceSum.Add(IntValue(1))
}
interfaceTime := time.Since(start)
fmt.Printf(" 泛型版本耗时: %v\\n", genericTime)
fmt.Printf(" 接口版本耗时: %v\\n", interfaceTime)
fmt.Printf(" 性能提升: %.2fx\\n", float64(interfaceTime)/float64(genericTime))
// 何时使用泛型
fmt.Printf(" 何时使用泛型:\\n")
fmt.Printf(" 数据结构实现\\n")
fmt.Printf(" 算法函数\\n")
fmt.Printf(" 工具函数\\n")
fmt.Printf(" 类型安全的容器\\n")
fmt.Printf(" 减少代码重复\\n")
fmt.Printf("\\n")
fmt.Printf(" 简单的业务逻辑\\n")
fmt.Printf(" 只有一种类型的场景\\n")
fmt.Printf(" 过度抽象的设计\\n")
fmt.Printf(" 性能敏感且类型固定的代码\\n")
// 迁移策略
fmt.Printf(" 迁移策略:\\n")
fmt.Printf(" 1. 识别重复代码模式\\n")
fmt.Printf(" 2. 从简单场景开始\\n")
fmt.Printf(" 3. 逐步替换类型断言\\n")
fmt.Printf(" 4. 保持向后兼容\\n")
fmt.Printf(" 5. 充分测试泛型代码\\n")
fmt.Println()
}