Go 1.18的发布标志着Go语言进入了一个新的时代——泛型时代。泛型的引入解决了Go语言长期以来在类型安全和代码复用方面的痛点,让Go语言在保持简洁性的同时,获得了更强的表达力。
// 泛型基础示例
func genericBasics() {
// 泛型函数
fmt.Println(max(10, 20)) // 输出: 20
fmt.Println(max(3.14, 2.71)) // 输出: 3.14
fmt.Println(max("apple", "banana")) // 输出: banana
// 泛型类型
var intStack Stack[int]
intStack.Push(1)
intStack.Push(2)
fmt.Println(intStack.Pop()) // 输出: 2
var stringStack Stack[string]
stringStack.Push("hello")
stringStack.Push("world")
fmt.Println(stringStack.Pop()) // 输出: world
}
// 泛型函数
func max[T comparable](a, b T) T {
if a > b {
return a
}
return b
}
// 泛型类型
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 {
var zero T
return zero
}
item := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return item
}
类型参数语法
// 类型参数语法
func typeParameterSyntax() {
// 1. 函数类型参数
func identity[T any](x T) T {
return x
}
// 2. 类型类型参数
type Container[T any] struct {
value T
}
// 3. 方法类型参数
func (c *Container[T]) Set(value T) {
c.value = value
}
func (c *Container[T]) Get() T {
return c.value
}
// 使用示例
container := &Container[int]{value: 42}
fmt.Printf("容器值: %d
", container.Get())
container.Set(100)
fmt.Printf("新值: %d
", container.Get())
}
类型约束
基本约束
// 基本类型约束
func basicConstraints() {
// 1. comparable约束 - 可比较类型
func findIndex[T comparable](slice []T, target T) int {
for i, v := range slice {
if v == target {
return i
}
}
return -1
}
// 2. any约束 - 任意类型
func printValue[T any](value T) {
fmt.Printf("值: %v
", value)
}
// 3. 自定义约束
type Numeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
~float32 | ~float64
}
func add[T Numeric](a, b T) T {
return a + b
}
// 使用示例
numbers := []int{1, 2, 3, 4, 5}
index := findIndex(numbers, 3)
fmt.Printf("索引: %d
", index)
printValue("Hello, World!")
printValue(42)
printValue(3.14)
result := add(10, 20)
fmt.Printf("加法结果: %d
", result)
}
复杂约束
// 复杂约束
func complexConstraints() {
// 1. 方法约束
type Stringer interface {
String() string
}
func printString[T Stringer](value T) {
fmt.Println(value.String())
}
// 2. 组合约束
type ComparableStringer interface {
comparable
String() string
}
func compareAndPrint[T ComparableStringer](a, b T) {
if a == b {
fmt.Printf("相等: %s
", a.String())
} else {
fmt.Printf("不相等: %s != %s
", a.String(), b.String())
}
}
// 3. 类型集约束
type Ordered interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
~float32 | ~float64 | ~string
}
func sortSlice[T Ordered](slice []T) []T {
result := make([]T, len(slice))
copy(result, slice)
// 简单的冒泡排序
for i := 0; i < len(result)-1; i++ {
for j := 0; j < len(result)-i-1; j++ {
if result[j] > result[j+1] {
result[j], result[j+1] = result[j+1], result[j]
}
}
}
return result
}
// 使用示例
numbers := []int{3, 1, 4, 1, 5, 9, 2, 6}
sorted := sortSlice(numbers)
fmt.Printf("排序结果: %v
", sorted)
strings := []string{"banana", "apple", "cherry"}
sortedStrings := sortSlice(strings)
fmt.Printf("字符串排序: %v
", sortedStrings)
}
泛型数据结构
泛型容器
// 泛型容器
func genericContainers() {
// 1. 泛型切片
type GenericSlice[T any] []T
func (s GenericSlice[T]) Filter(predicate func(T) bool) GenericSlice[T] {
var result GenericSlice[T]
for _, item := range s {
if predicate(item) {
result = append(result, item)
}
}
return result
}
func (s GenericSlice[T]) Map[U any](mapper func(T) U) GenericSlice[U] {
result := make(GenericSlice[U], len(s))
for i, item := range s {
result[i] = mapper(item)
}
return result
}
// 2. 泛型映射
type GenericMap[K comparable, V any] map[K]V
func (m GenericMap[K, V]) Get(key K) (V, bool) {
value, ok := m[key]
return value, ok
}
func (m GenericMap[K, V]) Set(key K, value V) {
m[key] = value
}
func (m GenericMap[K, V]) Keys() []K {
keys := make([]K, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
}
// 使用示例
numbers := GenericSlice[int]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
evens := numbers.Filter(func(n int) bool {
return n%2 == 0
})
fmt.Printf("偶数: %v
", evens)
squares := numbers.Map(func(n int) int {
return n * n
})
fmt.Printf("平方: %v
", squares)
userMap := make(GenericMap[string, int])
userMap.Set("Alice", 25)
userMap.Set("Bob", 30)
if age, ok := userMap.Get("Alice"); ok {
fmt.Printf("Alice的年龄: %d
", age)
}
}
泛型队列和栈
// 泛型队列和栈
func genericQueueAndStack() {
// 1. 泛型队列
type Queue[T any] struct {
items []T
}
func NewQueue[T any]() *Queue[T] {
return &Queue[T]{
items: make([]T, 0),
}
}
func (q *Queue[T]) Enqueue(item T) {
q.items = append(q.items, item)
}
func (q *Queue[T]) Dequeue() (T, bool) {
if len(q.items) == 0 {
var zero T
return zero, false
}
item := q.items[0]
q.items = q.items[1:]
return item, true
}
func (q *Queue[T]) Size() int {
return len(q.items)
}
// 2. 泛型栈
type Stack[T any] struct {
items []T
}
func NewStack[T any]() *Stack[T] {
return &Stack[T]{
items: make([]T, 0),
}
}
func (s *Stack[T]) Push(item T) {
s.items = append(s.items, item)
}
func (s *Stack[T]) Pop() (T, bool) {
if len(s.items) == 0 {
var zero T
return zero, false
}
index := len(s.items) - 1
item := s.items[index]
s.items = s.items[:index]
return item, true
}
func (s *Stack[T]) Peek() (T, bool) {
if len(s.items) == 0 {
var zero T
return zero, false
}
return s.items[len(s.items)-1], true
}
// 使用示例
queue := NewQueue[string]()
queue.Enqueue("first")
queue.Enqueue("second")
queue.Enqueue("third")
for queue.Size() > 0 {
if item, ok := queue.Dequeue(); ok {
fmt.Printf("出队: %s
", item)
}
}
stack := NewStack[int]()
stack.Push(1)
stack.Push(2)
stack.Push(3)
for {
if item, ok := stack.Pop(); ok {
fmt.Printf("出栈: %d
", item)
} else {
break
}
}
}
泛型算法
泛型排序
// 泛型排序
func genericSorting() {
// 1. 泛型快速排序
func quickSort[T Ordered](slice []T) {
if len(slice) < 2 {
return
}
pivot := slice[len(slice)/2]
left, right := 0, len(slice)-1
for left <= right {
for slice[left] < pivot {
left++
}
for slice[right] > pivot {
right--
}
if left <= right {
slice[left], slice[right] = slice[right], slice[left]
left++
right--
}
}
quickSort(slice[:right+1])
quickSort(slice[left:])
}
// 2. 泛型二分查找
func binarySearch[T Ordered](slice []T, target T) int {
left, right := 0, len(slice)-1
for left <= right {
mid := (left + right) / 2
if slice[mid] == target {
return mid
} else if slice[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}
return -1
}
// 3. 泛型归并排序
func mergeSort[T Ordered](slice []T) []T {
if len(slice) < 2 {
return slice
}
mid := len(slice) / 2
left := mergeSort(slice[:mid])
right := mergeSort(slice[mid:])
return merge(left, right)
}
func merge[T Ordered](left, right []T) []T {
result := make([]T, 0, len(left)+len(right))
i, j := 0, 0
for i < len(left) && j < len(right) {
if left[i] <= right[j] {
result = append(result, left[i])
i++
} else {
result = append(result, right[j])
j++
}
}
result = append(result, left[i:]...)
result = append(result, right[j:]...)
return result
}
// 使用示例
numbers := []int{64, 34, 25, 12, 22, 11, 90}
fmt.Printf("原始数组: %v
", numbers)
quickSort(numbers)
fmt.Printf("快速排序: %v
", numbers)
index := binarySearch(numbers, 25)
fmt.Printf("二分查找25的索引: %d
", index)
unsorted := []int{64, 34, 25, 12, 22, 11, 90}
sorted := mergeSort(unsorted)
fmt.Printf("归并排序: %v
", sorted)
}
泛型搜索
// 泛型搜索
func genericSearch() {
// 1. 泛型线性搜索
func linearSearch[T comparable](slice []T, target T) int {
for i, v := range slice {
if v == target {
return i
}
}
return -1
}
// 2. 泛型条件搜索
func findFirst[T any](slice []T, predicate func(T) bool) (T, bool) {
for _, v := range slice {
if predicate(v) {
return v, true
}
}
var zero T
return zero, false
}
// 3. 泛型过滤
func filter[T any](slice []T, predicate func(T) bool) []T {
var result []T
for _, v := range slice {
if predicate(v) {
result = append(result, v)
}
}
return result
}
// 4. 泛型映射
func mapSlice[T, U any](slice []T, mapper func(T) U) []U {
result := make([]U, len(slice))
for i, v := range slice {
result[i] = mapper(v)
}
return result
}
// 使用示例
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
index := linearSearch(numbers, 5)
fmt.Printf("线性搜索5的索引: %d
", index)
if value, ok := findFirst(numbers, func(n int) bool {
return n > 5
}); ok {
fmt.Printf("第一个大于5的数: %d
", value)
}
evens := filter(numbers, func(n int) bool {
return n%2 == 0
})
fmt.Printf("偶数: %v
", evens)
squares := mapSlice(numbers, func(n int) int {
return n * n
})
fmt.Printf("平方: %v
", squares)
}
泛型接口
泛型接口定义
// 泛型接口
func genericInterfaces() {
// 1. 泛型接口
type Container[T any] interface {
Add(item T)
Remove(item T) bool
Contains(item T) bool
Size() int
}
// 2. 泛型比较接口
type Comparable[T any] interface {
Compare(other T) int
}
// 3. 泛型迭代器接口
type Iterator[T any] interface {
Next() bool
Value() T
}
// 实现泛型接口
type GenericSet[T comparable] struct {
items map[T]bool
}
func NewGenericSet[T comparable]() *GenericSet[T] {
return &GenericSet[T]{
items: make(map[T]bool),
}
}
func (s *GenericSet[T]) Add(item T) {
s.items[item] = true
}
func (s *GenericSet[T]) Remove(item T) bool {
if s.items[item] {
delete(s.items, item)
return true
}
return false
}
func (s *GenericSet[T]) Contains(item T) bool {
return s.items[item]
}
func (s *GenericSet[T]) Size() int {
return len(s.items)
}
// 使用示例
set := NewGenericSet[int]()
set.Add(1)
set.Add(2)
set.Add(3)
fmt.Printf("集合大小: %d
", set.Size())
fmt.Printf("包含2: %t
", set.Contains(2))
set.Remove(2)
fmt.Printf("移除2后大小: %d
", set.Size())
fmt.Printf("包含2: %t
", set.Contains(2))
}
泛型方法
// 泛型方法
func genericMethods() {
// 1. 泛型方法
type Processor[T any] struct {
data T
}
func (p *Processor[T]) Process[U any](mapper func(T) U) U {
return mapper(p.data)
}
func (p *Processor[T]) Transform[U any](transformer func(T) U) *Processor[U] {
return &Processor[U]{data: transformer(p.data)}
}
// 2. 泛型链式调用
type Chain[T any] struct {
value T
}
func NewChain[T any](value T) *Chain[T] {
return &Chain[T]{value: value}
}
func (c *Chain[T]) Map[U any](mapper func(T) U) *Chain[U] {
return &Chain[U]{value: mapper(c.value)}
}
func (c *Chain[T]) Filter(predicate func(T) bool) *Chain[T] {
if predicate(c.value) {
return c
}
return nil
}
func (c *Chain[T]) Value() T {
return c.value
}
// 使用示例
processor := &Processor[int]{data: 42}
result := processor.Process(func(x int) string {
return fmt.Sprintf("数字: %d", x)
})
fmt.Printf("处理结果: %s
", result)
transformed := processor.Transform(func(x int) float64 {
return float64(x) * 2.5
})
fmt.Printf("转换结果: %.2f
", transformed.data)
chain := NewChain(10)
result2 := chain.Map(func(x int) int {
return x * 2
}).Map(func(x int) string {
return fmt.Sprintf("结果: %d", x)
}).Value()
fmt.Printf("链式调用结果: %s
", result2)
}
类型推断
自动类型推断
// 类型推断
func typeInference() {
// 1. 自动类型推断
func identity[T any](x T) T {
return x
}
// 编译器自动推断类型
result1 := identity(42) // T 被推断为 int
result2 := identity("hello") // T 被推断为 string
result3 := identity(3.14) // T 被推断为 float64
fmt.Printf("结果1: %d
", result1)
fmt.Printf("结果2: %s
", result2)
fmt.Printf("结果3: %.2f
", result3)
// 2. 显式类型指定
result4 := identity[int](42) // 显式指定 T 为 int
result5 := identity[string]("world") // 显式指定 T 为 string
fmt.Printf("显式类型结果1: %d
", result4)
fmt.Printf("显式类型结果2: %s
", result5)
// 3. 复杂类型推断
func process[T any](slice []T, processor func(T) T) []T {
result := make([]T, len(slice))
for i, v := range slice {
result[i] = processor(v)
}
return result
}
numbers := []int{1, 2, 3, 4, 5}
doubled := process(numbers, func(x int) int {
return x * 2
})
fmt.Printf("翻倍结果: %v
", doubled)
strings := []string{"hello", "world"}
uppercased := process(strings, func(s string) string {
return strings.ToUpper(s)
})
fmt.Printf("大写结果: %v
", uppercased)
}
实战应用
泛型缓存
// 泛型缓存
func genericCache() {
type Cache[K comparable, V any] struct {
mu sync.RWMutex
data map[K]V
maxSize int
}
func NewCache[K comparable, V any](maxSize int) *Cache[K, V] {
return &Cache[K, V]{
data: make(map[K]V),
maxSize: maxSize,
}
}
func (c *Cache[K, V]) Get(key K) (V, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
value, ok := c.data[key]
return value, ok
}
func (c *Cache[K, V]) Set(key K, value V) {
c.mu.Lock()
defer c.mu.Unlock()
if len(c.data) >= c.maxSize {
// 简单的LRU实现:删除第一个元素
for k := range c.data {
delete(c.data, k)
break
}
}
c.data[key] = value
}
func (c *Cache[K, V]) Delete(key K) {
c.mu.Lock()
defer c.mu.Unlock()
delete(c.data, key)
}
func (c *Cache[K, V]) Size() int {
c.mu.RLock()
defer c.mu.RUnlock()
return len(c.data)
}
// 使用示例
cache := NewCache[string, int](3)
cache.Set("one", 1)
cache.Set("two", 2)
cache.Set("three", 3)
if value, ok := cache.Get("one"); ok {
fmt.Printf("缓存命中: one = %d
", value)
}
cache.Set("four", 4) // 会触发LRU
fmt.Printf("缓存大小: %d
", cache.Size())
}
泛型API响应
// 泛型API响应
func genericAPIResponse() {
type APIResponse[T any] struct {
Success bool `json:"success"`
Message string `json:"message"`
Data T `json:"data,omitempty"`
}
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price"`
}
// 创建用户响应
userResp := APIResponse[User]{
Success: true,
Message: "获取用户成功",
Data: User{
ID: 1,
Name: "Alice",
Email: "alice@example.com",
},
}
// 创建产品响应
productResp := APIResponse[Product]{
Success: true,
Message: "获取产品成功",
Data: Product{
ID: 1,
Name: "Laptop",
Price: 999.99,
},
}
// 创建列表响应
usersResp := APIResponse[[]User]{
Success: true,
Message: "获取用户列表成功",
Data: []User{
{ID: 1, Name: "Alice", Email: "alice@example.com"},
{ID: 2, Name: "Bob", Email: "bob@example.com"},
},
}
fmt.Printf("用户响应: %+v
", userResp)
fmt.Printf("产品响应: %+v
", productResp)
fmt.Printf("用户列表响应: %+v
", usersResp)
}
性能思考
泛型性能
// 泛型性能
func genericPerformance() {
// 1. 泛型函数的性能
func genericAdd[T Numeric](a, b T) T {
return a + b
}
// 2. 非泛型函数的性能
func intAdd(a, b int) int {
return a + b
}
// 性能测试
func benchmarkGenericAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = genericAdd(10, 20)
}
}
func benchmarkIntAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = intAdd(10, 20)
}
}
// 3. 泛型类型的性能
type GenericContainer[T any] struct {
value T
}
type IntContainer struct {
value int
}
// 泛型容器的性能一般与非泛型容器相当
// 由于Go编译器会进行单态化
}
最佳实践
泛型最佳实践
// 泛型最佳实践
func genericBestPractices() {
// 1. 使用有意义的约束
type Numeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
~float32 | ~float64
}
// 2. 避免过度泛型化
// 不要为了泛型而泛型,只在真正需要时使用
// 3. 使用类型别名提高可读性
type UserID = int
type ProductID = int
type User struct {
ID UserID
Name string
}
type Product struct {
ID ProductID
Name string
Price float64
}
// 4. 合理使用类型推断
func process[T any](data T) T {
return data
}
// 让编译器推断类型
result := process(42)
fmt.Printf("推断结果: %d
", result)
// 5. 使用泛型接口提高灵活性
type Repository[T any] interface {
Save(entity T) error
FindByID(id int) (T, error)
Delete(id int) error
}
// 6. 思考向后兼容性
// 在现有代码中引入泛型时要小心
}
写在最后
泛型是Go语言发展史上的重大里程碑,它让Go语言在保持简洁性的同时,获得了更强的表达力。从简单的类型参数到复杂的约束系统,泛型为Go语言带来了革命性的变化。
作为Go开发者,掌握泛型的使用不仅能够提高代码的类型安全性和可复用性,还能让我们更好地理解Go语言的设计哲学。通过合理使用泛型,我们可以构建出更加优雅和类型安全的Go程序。
记住,泛型不仅仅是工具,更是Go语言表达力的体现。通过泛型,我们可以实现更加灵活和强劲的类型系统,构建出更加优雅和可维护的Go程序。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...





