Golang中泛型方法的使用探讨

Golang中泛型方法的使用探讨 假设我想在 Go 1.18beta1 中为泛型切片实现一个 “map” 函数… 方法的原型应该类似于:

func (xs List[T]) Map(fct func(x T) S) List[S] {...}

假设 List[T] 定义为:

type List[T any] []T

遗憾的是,我还没有找到如何在方法声明中引入 S 泛型参数。这甚至可能实现吗?

6 回复

好的,谢谢你的建议……

更多关于Golang中泛型方法的使用探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我同意,嵌套函数比链式函数更难阅读,但另一方面,使用自定义泛型切片类型的代码(通常)也比使用标准切片的代码更难阅读。

是的,我会这么做的……我原本更倾向于使用点号表示法来简化调用链,不过没关系……

我觉得 xs.map(fct).filter(pred)filter(map(xs, fct), pred) 更清晰……但我也可以接受……

我不太熟悉 Go 语言中的泛型,但在 Reddit 上到处都能看到关于想要一个 Map 函数的这个具体问题,据我理解,你无法做到这一点,因为只有顶层函数才能拥有多个泛型参数。

如果你放弃定义自定义切片类型的要求,map 函数可以很好地工作:

func Map[T, S any](t []T, fct func(x T) S) []S {
	var s []S
	for _, x := range t {
		s = append(s, fct(x))
	}
	return s
}

func main() {
	t := []int{1, 2, 3}
	s := Map(t, func(n int) int64 {
		return int64(n)
	})
	fmt.Println(s)
}

Go Playground - The Go Programming Language

关键在于,内置的切片类型已经是泛型的了,因此自定义的泛型切片类型可能并非必需(除非出于某些其他原因需要它)。

在 Go 1.18 及更高版本中,确实可以在方法上声明额外的类型参数。你需要将类型参数 S 放在方法名之后的方括号中。以下是实现示例:

package main

import "fmt"

type List[T any] []T

// Map 方法在方法名后声明了额外的类型参数 S
func (xs List[T]) Map[S any](f func(T) S) List[S] {
    result := make(List[S], len(xs))
    for i, x := range xs {
        result[i] = f(x)
    }
    return result
}

func main() {
    intList := List[int]{1, 2, 3, 4, 5}
    
    // 将 int 转换为 string
    strList := intList.Map(func(x int) string {
        return fmt.Sprintf("Number: %d", x)
    })
    
    fmt.Println(strList) // [Number: 1 Number: 2 Number: 3 Number: 4 Number: 5]
    
    // 将 int 转换为 float64
    floatList := intList.Map(func(x int) float64 {
        return float64(x) * 1.5
    })
    
    fmt.Println(floatList) // [1.5 3 4.5 6 7.5]
}

关键点:

  1. 方法类型参数 [S any] 紧接在方法名 Map 之后
  2. 返回类型 List[S] 使用了新引入的类型参数
  3. 转换函数 func(T) S 的签名与类型参数匹配

这种方法声明完全符合 Go 泛型规范,允许在方法上定义独立的类型参数,提供了灵活的类型转换能力。

回到顶部