使用Golang中的泛型创建“map”函数 - gosamples


map()函数是另一种函数式编程范式,由于新的泛型功能,它可以在Go中轻松实现。
它的工作原理是应用一个函数,将单个slice元素作为参数,对其进行转换,并返回输出值,其中采取和返回的类型不一定相同。
例如,你可以使用map()函数将字符串转换成int的slice;或者格式化字符串的slice的每个元素,而不改变输出类型。
在使用泛型函数时,这种不同的用例是没有问题的,因为map()可以在任何输入和输出类型上运行。

package main

import (
    "fmt"
    "math"
    "strconv"
)

func mapSlice[T any, M any](a []T, f func(T) M) []M {
    n := make([]M, len(a))
    for i, e := range a {
        n[i] = f(e)
    }
    return n
}

func main() {
    numbers := []float64{4, 9, 16, 25}

    newNumbers := mapSlice(numbers, math.Sqrt)
    fmt.Println(newNumbers)

    words := []string{"a", "b", "c", "d"}
    quoted := mapSlice(words, func(s string) string {
        return "\"" + s + "\""
    })
    fmt.Println(quoted)

    stringPowNumbers := mapSlice(numbers, func(n float64) string {
        return strconv.FormatFloat(math.Pow(n, 2), 'f', -1, 64)
    })
    fmt.Println(stringPowNumbers)
}
输出:
[2 3 4 5]
["a" "b" "c" "d"]
[16 81 256 625]

这里mapSlice()函数(我们使用mapSlice()这个名字是因为map是Golang的关键字)需要两个类型参数:
T是输入slice的类型,M是输出slice的类型。
它们都可以是任何类型。
这个函数也需要两个参数:slice a和转换其每个元素的函数f。
mapSlice()的工作原理是创建一个与输入相同长度的新的输出slice,并通过使用f函数在一个循环中把输入slice的每个元素转换为输出slice。
这段简单的代码足以得到一个通用的map()函数,如例子所示,它可以将slice中的浮点64元素平方化,通过添加引号来格式化字符串,或者将数字提高到一个幂。