求Golang的泛型编程实例

最近在学习Golang的泛型编程,但对具体实现还有些困惑。能否提供一个实际的泛型编程案例?比如如何用泛型实现一个通用的集合操作函数(如过滤、映射等)?最好能说明类型参数约束的使用场景,以及和之前用interface{}实现的方式相比有哪些改进。

3 回复

以下是一个Go语言中使用泛型的简单实例:

package main

import "fmt"

// 定义一个泛型函数,用于交换两个值
func Swap[T any](a *T, b *T) {
	*a, *b = *b, *a
}

func main() {
	var x int = 10
	var y int = 20
	Swap(&x, &y)
	fmt.Println("Integers:", x, y)

	var a string = "hello"
	var b string = "world"
	Swap(&a, &b)
	fmt.Println("Strings:", a, b)
}

解释:

  • Swap 是一个泛型函数,[T any] 表示它可以处理任意类型。
  • 函数接收两个指向 T 类型的指针参数,并交换它们的值。
  • main 函数中,我们分别传入整数和字符串作为参数。

这个例子展示了Go 1.18引入的泛型特性,它允许编写更通用、可复用的代码。

更多关于求Golang的泛型编程实例的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


以下是一个Go语言泛型编程的简单实例,展示如何使用泛型来处理不同类型的整数和字符串:

package main

import "fmt"

// 定义一个泛型函数,用于交换两个值
func Swap[T any](a *T, b *T) {
	*a, *b = *b, *a
}

func main() {
	var x int = 10
	var y int = 20
	Swap(&x, &y)
	fmt.Println("交换后:", x, y)

	var s1 string = "hello"
	var s2 string = "world"
	Swap(&s1, &s2)
	fmt.Println("交换后:", s1, s2)
}

这个例子中,Swap 是一个泛型函数,可以对任何类型的数据进行交换操作。通过 any 约束,允许传入任意类型的数据指针。在 main 函数中,分别对整数和字符串调用了该泛型函数,展示了泛型的灵活性。

Go语言泛型编程实例

Go语言在1.18版本正式引入了泛型(Generics)特性,下面通过几个实例展示如何使用Go泛型。

基础示例:泛型函数

package main

import "fmt"

// 泛型函数,可以处理任何可比较的类型
func Max[T comparable](a, b T) T {
    if a > b {
        return a
    }
    return b
}

func main() {
    fmt.Println(Max(3, 5))       // 输出: 5
    fmt.Println(Max(3.14, 2.71)) // 输出: 3.14
    fmt.Println(Max("a", "b"))   // 输出: b
}

泛型切片操作

package main

import "fmt"

// 泛型切片过滤函数
func Filter[T any](s []T, f func(T) bool) []T {
    var result []T
    for _, v := range s {
        if f(v) {
            result = append(result, v)
        }
    }
    return result
}

func main() {
    numbers := []int{1, 2, 3, 4, 5, 6}
    even := Filter(numbers, func(n int) bool {
        return n%2 == 0
    })
    fmt.Println(even) // 输出: [2 4 6]
}

泛型结构体

package main

import "fmt"

// 泛型栈结构
type Stack[T any] struct {
    elements []T
}

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

func (s *Stack[T]) Pop() (T, bool) {
    if len(s.elements) == 0 {
        var zero T
        return zero, false
    }
    element := s.elements[len(s.elements)-1]
    s.elements = s.elements[:len(s.elements)-1]
    return element, true
}

func main() {
    stack := Stack[int]{}
    stack.Push(1)
    stack.Push(2)
    stack.Push(3)
    
    if elem, ok := stack.Pop(); ok {
        fmt.Println(elem) // 输出: 3
    }
}

类型约束

package main

import (
    "fmt"
    "golang.org/x/exp/constraints"
)

// 使用constraints包中的类型约束
func Sum[T constraints.Integer | constraints.Float](numbers []T) T {
    var total T
    for _, num := range numbers {
        total += num
    }
    return total
}

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

注意事项:

  1. 类型参数用方括号 [] 表示
  2. any 表示任何类型,相当于 interface{}
  3. comparable 表示可比较的类型
  4. 可以使用 | 创建类型约束的联合
回到顶部