Golang 泛型的使用
Golang 在 1.18 版本引入了泛型,为开发者提供了更强大和灵活的编程能力。
一、泛型函数
泛型函数可以接受不同类型的参数,并进行通用的操作。
package main
import "fmt"
func Map[T any](slice []T, f func(T) T) []T {
result := make([]T, len(slice))
for i, v := range slice {
result[i] = f(v)
}
return result
}
func Double[T int | float64](num T) T {
return num * 2
}
func main() {
intSlice := []int{1, 2, 3, 4, 5}
intResult := Map(intSlice, Double[int])
fmt.Println(intResult)
floatSlice := []float64{1.1, 2.2, 3.3, 4.4, 5.5}
floatResult := Map(floatSlice, Double[float64])
fmt.Println(floatResult)
}
在上述示例中,Map
函数是一个泛型函数,它可以对不同类型的切片进行操作。
二、泛型类型
除了泛型函数,还可以定义泛型类型。
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 {
if len(s.elements) == 0 {
panic("Stack is empty")
}
last := s.elements[len(s.elements)-1]
s.elements = s.elements[:len(s.elements)-1]
return last
}
func main() {
intStack := Stack[int]{}
intStack.Push(1)
intStack.Push(2)
intStack.Push(3)
fmt.Println(intStack.Pop())
fmt.Println(intStack.Pop())
}
这里定义了一个泛型的栈 Stack
。
三、类型约束
在泛型中,可以使用类型约束来限制泛型类型的范围。
package main
import "fmt"
type Number interface {
int | int8 | int16 | int32 | int64 | float32 | float64
}
func Sum[T Number](slice []T) T {
var sum T
for _, v := range slice {
sum += v
}
return sum
}
func main() {
intSlice := []int{1, 2, 3, 4, 5}
fmt.Println(Sum(intSlice))
}
通过定义 Number
接口作为类型约束,确保 Sum
函数只处理特定的数字类型。
补充阅读:
FAQ:
- 泛型会影响程序的性能吗?
- 一般来说,合理使用泛型不会对性能产生明显的负面影响,反而能提高代码的复用性和可读性。
- 如何确定是否应该使用泛型?
- 当需要对不同类型执行相似的逻辑操作,且避免重复代码时,泛型是一个不错的选择。