🔑 在 Go 中使用泛型获取 Map 的有序键列表 🔗

在 Go 语言中,哈希表(map)天生是无序的。当你使用 for range 循环遍历一个 map 时,每次的遍历顺序都是随机化的。在引入泛型之前,开发者不得不针对不同类型编写繁琐的样板代码或特定类型的函数来提取并排序 map 的键。

借助现代 Go 泛型以及标准库包(cmp 和 slices),实现一个干净、可复用的 SortedKeys 函数变得异常简单且紧凑。

📑 目录 🔗


💻 现代实现方案(Go 1.21+) 🔗

package main

import (
	"cmp"
	"slices"
	"fmt"
)

// SortedKeys 从 map 中提取所有键,并以升序排序后返回。
// 它适用于键类型为任何可排序类型(整数、浮点数、字符串)的 map。
func SortedKeys[K cmp.Ordered, V any](m map[K]V) []K {
	r := make([]K, 0, len(m))
	for k := range m {
		r = append(r, k)
	}
	slices.Sort(r)
	return r
}

func main() {
	// 示例 1:整型键
	intMap := map[int]string{3: "three", 1: "one", 2: "two"}
	fmt.Println(SortedKeys(intMap))
	// Output: [1 2 3]

	// 示例 2:字符串键
	strMap := map[string]int{"banana": 2, "apple": 4, "cherry": 1}
	fmt.Println(SortedKeys(strMap))
	// Output: [apple banana cherry]
}

⚙️ 工作原理 🔗

  1. 泛型类型约束(K cmp.Ordered, V any):
    • K cmp.Ordered 将 map 的键限制为支持比较运算符(<、>、<=、>=)的类型,例如整数、浮点数和字符串。
    • V any 允许 map 的值为任意类型(any 是 interface{} 的类型别名)。
  2. 预先分配切片容量:
    • make([]K, 0, len(m)) 预先分配了一个容量等于 map 长度的切片,从而避免了在 append 循环过程中触发开销高昂的动态内存重新分配。
  3. 提取所有键:
    • for k := range m 循环将所有键收集到切片中。
  4. 原地排序:
    • slices.Sort(r) 使用 Go 高度优化的排序算法对键切片进行原地排序。

🚀 为什么这个版本比 2020 年的设计草案更好 🔗

在 2020 年 6 月,当 Go 泛型还处于设计草案阶段时,开发者必须手动定义自定义类型并实现 sort.Interface 接口:

// Go 1.18 之前的早期设计草案写法(已过时)
type Ordered interface {
	type int, int8, ... // 接口中的类型列表
}

type orderedSlice[T Ordered] []T
func (s orderedSlice[T]) Len() int           { return len(s) }
func (s orderedSlice[T]) Less(i, j int) bool { return s[i] < s[j] }
func (s orderedSlice[T]) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

如今,现代 Go 标准库直接提供了:


📚 免费下载我的电子书 🔗

获取《卡乌埃的生活方式》精选离线版——一份全面优化 🍏 健康、💰 财富、❤️ 爱 与 🧘 意义 的实践指南。

卡乌埃的生活方式

卡乌埃的生活方式

📬 订阅邮件通讯 🔗

当我发布关于美好生活的新随笔、读书笔记和实践指南时接收通知。绝无垃圾邮件——可随时退订。


💬 评论与讨论 🔗

有任何问题、见解或建议吗?欢迎在下方分享您的想法。评论功能由 GitHub Discussions 驱动(无广告、无垃圾信息)——点击下方的使用 GitHub 登录即可发表评论或互动(注册免费 GitHub 账号不到一分钟即可完成)。



最后更新于 2026年10月11日.

免责声明:本站所有内容仅供信息参考与教育用途,不构成任何医疗、心理、财务、投资、税务或法律建议。此处呈现的观点、整理与见解仅代表我个人,不代表我雇主的立场。书籍、演讲及文章摘要均为独立的教育性评论,其知识产权归原作者所有。本站可能使用 AI 工具辅助编辑、排版与归纳;尽管我们竭力确保准确无误,但仍可能存在疏漏。隐私政策:本站使用第三方服务提供可选的邮件通讯订阅(follow.it)、评论(giscus / GitHub Discussions)以及嵌入媒体(YouTube),这些服务可能会依据各自的隐私政策处理访客的 IP 地址和 Cookie。