在Go中使用泛型函数创建一个分片 "map() "函数的方法

139 阅读2分钟

map() 函数是另一种函数式编程范式,由于新的泛型功能,它可以在Go中轻松实现。它的工作原理是应用一个函数,将单个切片元素作为参数,对其进行转换,并返回输出值,其中取自和返回的类型不一定相同。例如,你可以使用map() 函数将string 转换为int片断;或者格式化string 片断的每个元素,而不改变输出类型。在使用泛型函数时,这种不同的用例不会有问题,因为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 是输入分片的类型,M 是输出分片的类型。它们都可以是任何类型。该函数还需要两个参数:切片a 和转换其每个元素的函数f 。注意,这个函数将输入类型T 的值转换为输出类型MmapSlice() 的工作原理是创建一个与输入相同长度的新输出片断,并通过使用f 函数在一个循环中将输入片断的每个元素转化为输出片断。这段简单的代码足以得到一个通用的map() 函数,如例子所示,它可以将切片中的float64 元素平方,通过添加引号来格式化字符串,或者将数字提高到一个幂。