在Golang中使用泛型从任何map中获取键的slice


在Go 1.18之前,当你想从Go中的map中提取一个键列表时,你必须编写代码来迭代map并将键添加到一个slice中。
从1.18起,有了新的泛型功能,你可以写一个单一的通用函数,从任何map中获取键,并在需要时使用它。不用再为特定类型的map编写代码了。
伴随着Go 1.18的发布,golang.org/x/exp/maps包也已经发布,Keys()函数的工作原理与下面的相同。

package main

import (
    "fmt"
)

func keys[K comparable, V any](m map[K]V) []K {
    keys := make([]K, 0, len(m))
    for k := range m {
        keys = append(keys, k)
    }
    return keys
}

func main() {
    vegetableSet := map[string]bool{
       
"potato":  true,
       
"cabbage": true,
       
"carrot":  true,
    }

    fruitRank := map[int]string{
        1:
"strawberry",
        2:
"raspberry",
        3:
"blueberry",
    }

    fmt.Printf(
"vegetableSet keys: %+v\n", keys(vegetableSet))
    fmt.Printf(
"fruitRank keys: %+v\n", keys(fruitRank))
}

keys()函数接受一个map作为参数,其中的键是具有可比较约束的类型,而值则具有any约束。
comparable约束描述了其值可以被比较的类型,这意味着==和!=运算符可以在它们身上使用。
any约束等同于interface{}:它接受任何类型,所以map的值可以是任何东西。

该函数的其余部分非常简单。它返回一个[]K的键slice,所以在函数主体的第一行,创建了所产生的slice。
注意,它的容量等于map的大小。然后,在一个循环中,每个map的键都被添加到生成的slice中。
用两个不同的map运行示例代码,你会得到这样的输出。

vegetableSet keys: [potato cabbage carrot]
fruitRank keys: [1 2 3]

这就是全部。现在,通过一个keys()函数,你可以得到任何map的keys列表。