当前位置:首页 > 文章列表 > Golang > Go教程 > Go maps.Values 怎样提取 map 值集合

Go maps.Values 怎样提取 map 值集合

来源:17golang原创 2026-10-20 05:00:17 0浏览 收藏

如果你的代码已经使用 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]。所以它更像“值的遍历入口”,而不是“立刻分配好的结果数组”。这个区别决定了后面该选择直接遍历还是收集。

Go maps.Values 从 map 输入到值迭代器再到 range 消费的静态关系说明图
图1:maps.Values 的静态职责关系说明图,展示 map、值迭代器和消费端之间的边界;这是原创说明图,不是运行截图。

只读取值时直接 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 适合“值本身就是排序对象”的情况。

Go maps.Values 的无序值集合与显式排序结果之间的静态关系说明图
图2:值集合的顺序边界说明图,展示无序迭代、切片收集和显式排序之间的职责关系;这是原创说明图,不是执行证据。

空 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 会在遍历和收集结果中保留多份。
版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go maps.Keys 怎样稳定拿到 map 键集合Go maps.Keys 怎样稳定拿到 map 键集合
上一篇
Go maps.Keys 怎样稳定拿到 map 键集合
Go strconv.ParseBool 怎样兼容配置里的 yes/no 字符串
下一篇
Go strconv.ParseBool 怎样兼容配置里的 yes/no 字符串
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    555次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    606次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    632次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    588次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    413次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码