Go maps.Values 怎样提取 map 值集合
如果你的代码已经使用 Go 1.23 或更高版本,提取 map 的值集合可以直接写成 maps.Values(m)。它返回的是一个值迭代器 iter.Seq[V],可以直接用 range 遍历,也可以交给 slices.Collect 收集成切片。
官方地址:https://pkg.go.dev/maps
我第一次把它用在配置快照导出时,最容易误判的地方是“值集合”听起来像一个已经排好序的 []V。实际情况正相反:maps.Values 只负责提供值,不承诺迭代顺序。下面按使用压力拆开这个边界。
maps.Values 返回的不是切片
标准库签名可以概括为:
func Values[Map ~map[K]V, K comparable, V any](m Map) iter.Seq[V]
它有三个关键信息:输入可以是底层类型为 map 的自定义类型;值类型可以是任意类型;返回值是 iter.Seq[V]。所以它更像“值的遍历入口”,而不是“立刻分配好的结果数组”。这个区别决定了后面该选择直接遍历还是收集。

只读取值时直接 range
如果目标只是统计、过滤、拼接或把值交给一个处理函数,没有必要先创建切片。直接遍历迭代器就够了:
package main
import (
"fmt"
"maps"
)
type Server struct {
Name string
Online bool
}
func main() {
servers := map[string]Server{
"api": {Name: "api", Online: true},
"worker": {Name: "worker", Online: false},
}
count := 0
for server := range maps.Values(servers) {
// 只消费值,不关心 key,也不创建中间切片。
if server.Online {
count++
}
}
fmt.Println("online:", count)
}
这里的 server 是值类型 Server,不是键值对。对只关心值的场景来说,这比先写一轮普通 for key, value := range m 再忽略 key 更直接。
需要 []V 时用 slices.Collect
当下游 API 明确要求切片,或者你要做切片索引、传递给其他切片函数,可以把迭代器收集起来:
package main
import (
"fmt"
"maps"
"slices"
)
func main() {
prices := map[string]int{
"book": 39,
"mouse": 89,
"cable": 19,
}
values := slices.Collect(maps.Values(prices))
// Collect 把 iter.Seq[int] 物化为 []int,方便传给切片 API。
fmt.Println(values)
}
slices.Collect 只改变容器形态,不会替你建立业务顺序。它得到的切片顺序仍然继承 map 遍历的不确定性;如果下游要稳定序列化、生成测试快照或展示列表,就还要单独排序。
需要稳定顺序时显式排序
对可排序的值,可以直接使用 slices.Sorted 消费 maps.Values:
package main
import (
"fmt"
"maps"
"slices"
)
func main() {
labels := map[int]string{
1: "one",
10: "Ten",
1000: "THOUSAND",
}
ordered := slices.Sorted(maps.Values(labels))
// Sorted 明确建立字符串升序,避免把 map 的遍历顺序当成业务顺序。
fmt.Println(ordered)
}
如果你的业务顺序来自 key,而不是 value 本身,那么“只取值再排序”可能丢失排序依据。此时应改为先收集键,或在普通 range 中同时保留 key 和 value,再按业务规则组织结果。maps.Values 适合“值本身就是排序对象”的情况。

空 map、nil map 与重复值怎么理解
maps.Values 不会把 map 的 key 重新编码到结果里,因此要记住三个边界:
| 场景 | 直接遍历 | 收集后结果 | 需要留意 |
|---|---|---|---|
| nil map | 不会遍历任何值 | 得到空集合语义 | 不要把它当成错误 |
| 空 map | 不会进入循环体 | 得到空切片 | 下游是否区分 nil 和空切片要看接口约定 |
| 不同 key 对应相同 value | 会遍历多次 | 结果保留重复值 | Values 不负责去重 |
| 需要稳定顺序 | 顺序不可依赖 | 仍不可依赖 | 显式排序或保留 key |
尤其是重复值:map 的 key 唯一,不代表 value 唯一。如果目标是得到去重后的值集合,需要额外使用一个集合结构记录已见值;这已经超出 maps.Values 本身的职责。
Go 1.22 及更早版本怎么办
maps.Values 是 Go 1.23 起的标准库能力。如果项目暂时不能升级,可以用普通 range 写出等价的值收集逻辑:
values := make([]string, 0, len(users))
for _, user := range users {
// 兼容旧版本 Go:忽略 key,只把 value 追加到切片。
values = append(values, user.Name)
}
这不是两个 API 的结果顺序差异,而是同一个 map 顺序边界的两种写法。升级到 Go 1.23 后,maps.Values 主要带来的是表达力和与迭代器生态的组合能力,不会自动把 map 变成有序容器。
我会怎样选择
- 只消费值:使用
for value := range maps.Values(m),避免无意义的中间切片。 - 下游明确要
[]V:使用slices.Collect(maps.Values(m))。 - 需要稳定的值排序:使用
slices.Sorted(maps.Values(m)),或收集后按业务比较器排序。 - 排序依据是 key、需要去重或要保留键值关系:不要只提取 values,保留普通
range的键值对。 - 项目低于 Go 1.23:继续使用普通
range,不要为了一个辅助函数强行改变工具链。
一句话总结:maps.Values 解决的是“怎样把 map 的值暴露为可遍历序列”,不解决切片物化、排序、去重或业务顺序。先判断下游真正需要什么,再决定直接遍历、收集,还是保留 key。
相关问题
- maps.Values 会返回稳定顺序吗?不会,官方文档明确说明顺序不指定,也不保证多次调用一致。
- 怎么把 maps.Values 变成切片?Go 1.23+ 使用
slices.Collect(maps.Values(m))。 - 怎么保证输出顺序?让值满足排序约束后使用
slices.Sorted,或者保留 key 按业务规则排序。 - maps.Values 会去重吗?不会,不同 key 的相同 value 会在遍历和收集结果中保留多份。
Go maps.Keys 怎样稳定拿到 map 键集合
- 上一篇
- Go maps.Keys 怎样稳定拿到 map 键集合
- 下一篇
- Go strconv.ParseBool 怎样兼容配置里的 yes/no 字符串
-
- Golang · Go教程 | 40分钟前 | 标准库 · JSON · go · Go token encoding/json/jsontext JSON token流
- Go encoding/json/jsontext 怎样读取 JSON token
- 271浏览 收藏
-
- Golang · Go教程 | 45分钟前 | Go crypto/mlkem ML-KEM-768 后量子密钥协商
- Go crypto/mlkem 怎样封装后量子密钥协商
- 406浏览 收藏
-
- Golang · Go教程 | 47分钟前 | 内存管理 · Go教程 · Go 垃圾回收 资源释放 runtime.AddCleanup
- Go runtime.AddCleanup 怎样注册对象清理回调
- 304浏览 收藏
-
- Golang · Go教程 | 47分钟前 | go · 泛型 · 内存优化 · Go Handle unique.Make 值唯一化
- Go unique.Make 怎样复用可比较值的唯一实例
- 329浏览 收藏
-
- Golang · Go教程 | 48分钟前 | go · 垃圾回收 ·
- Go weak.Pointer 怎样保存可回收对象的弱引用
- 175浏览 收藏
-
- Golang · Go教程 | 1小时前 | Go maps.Keys slices.Sorted map键集合
- Go maps.Keys 怎样稳定拿到 map 键集合
- 320浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 555次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 606次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 632次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 588次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 413次使用
-
- Java 性能优化上线清单:从定位、改造到灰度发布
- 2026-06-11 860浏览
-
- Spring Boot 压测验证:Gatling、JMeter 与性能回归门禁
- 2026-06-11 843浏览
-
- Java NMT 非堆内存排查:Direct Buffer、线程栈与 Metaspace 分析
- 2026-06-11 826浏览
-
- Spring Boot 容器内存优化:JVM 堆、非堆与 MaxRAMPercentage
- 2026-06-11 809浏览
-
- Tomcat 连接与线程参数调优:maxThreads、acceptCount 与 KeepAlive
- 2026-06-11 792浏览

