Go slices.Move 新提案:一次搬动,胜过两次删除插入

简介: 本文讲述Go开发者因TODO应用拖拽排序需求,写出低效“笨代码”的反思历程,引出社区提案`slices.Move`——用一次内存移动替代`Delete+Insert`两次复制,填补API空白。它不颠覆理论,却以实用主义提升性能与可读性,彰显Go“简洁而不简陋”的哲学。(239字)

一、一个让我写出“笨代码”的下午

去年写一个 TODO 应用时,我遇到一个需求:用户拖拽任务列表里的某个任务,改变它的优先级,列表要重新排序。

后端存储就是一个切片 []Task,按优先级排序。

用户把优先级从“低”改成“高”后,任务应该从列表尾部移动到头部附近。

我当时写的代码是这样的:

// 假设 tasks 是按优先级排序的切片
oldIdx := findTaskIndex(tasks, taskID)
task := tasks[oldIdx]
task.Priority = newPriority

// 删除旧位置
tasks = slices.Delete(tasks, oldIdx, oldIdx+1)

// 找到新位置并插入
newIdx := findNewPosition(tasks, task)
tasks = slices.Insert(tasks, newIdx, task)

跑是能跑。但我看着这段代码,总觉得哪里不对劲。

两次内存移动,做了两遍复制,还多了一次切片长度变更。

我问自己:Go 标准库有 slices.Delete,有 slices.Insert,为什么没有一个“把元素从A位置移动到B位置”的操作?

直到我看到了这个提案:slices.Move。

2026年5月31日,开发者 abemedia 在 Go 官方 issue 里提交了一个提案:给 slices 包增加一个 Move 函数。

当前做法(Delete + Insert):

// 移动元素:从索引 from 移动到 to
v := s[from]
s = slices.Delete(s, from, from+1)      // 第一次内存移动
s = slices.Insert(s, to, v)             // 第二次内存移动

提案做法(Move):

func Move[S ~[]E, E any](s S, from, to int) {
   
    if from == to {
   
        return
    }
    v := s[from]
    if from < to {
   
        copy(s[from:to], s[from+1:to+1])  // 向左移动
    } else {
   
        copy(s[to+1:from+1], s[to:from])  // 向右移动
    }
    s[to] = v
}

核心优化:一次 copy 完成,而不是两次。

使用示例:

// 排序的切片里,某个元素的键变了,需要重新调整位置
oldIdx, _ := slices.BinarySearchFunc(records, r, byPK)
r.PK = newValue
newIdx, _ := slices.BinarySearchFunc(records, r, byPK)
if newIdx > oldIdx {
   
    newIdx--
}
slices.Move(records, oldIdx, newIdx)  // 一行搞定,一次内存移动

这个提案的讨论区很有意思,有几个观点特别能代表 Go 社区的文化。

观点1:Go 核心成员的质疑

“移动单个元素需要 O(n) 代价,这通常意味着你选错了数据结构。”

这是典型的“核心团队视角”——从算法复杂度出发,认为切片不适合频繁移动元素。

观点2:提案作者的反驳

“slices.Insert 和 slices.Delete 已经是 O(n) 了。如果 O(n) 就意味着错,那这两个函数也不该存在。Move 只是填补空缺。”

这个反驳很犀利。它指出:Go 标准库已经有 O(n) 的切片操作了,为什么多一个 Move 就不行?

观点3:实用性辩护

“UI 列表重排、轻微变更的排序切片、小规模 LRU 缓存……这些场景里,切片是自然选择。CPU 缓存局部性带来的性能优势,远大于算法复杂度的理论劣势。”

这是“工程视角”——理论归理论,实际场景中切片就是好用。

观点4:rotate vs move

有人提出用 slices.Rotate 来替代 Move,还给了实现代码。但作者认为 Move 更直接、更符合直觉。

我觉得这个讨论很 Go:核心成员在乎理论正确性,社区开发者在乎实际痛点和代码可读性。 双方都没错,只是站位不同。

回到那个 TODO 应用。用户拖拽排序时,列表通常只有几十到几百个任务。Delete+Insert 确实能跑,但我心里一直有个“技术债”的感觉:每次移动都要写三行代码,还要小心处理切片覆盖。

更让我困扰的是,Delete 和 Insert 中间如果有其他操作(比如日志、验证),代码就变得更难读。

如果当时有 slices.Move:

slices.Move(tasks, oldIdx, newIdx)

一行,意图明确,性能翻倍。

这不是“能不能实现”的问题,而是“应该怎么表达”的问题。 代码是给人看的,Move 比 Delete+Insert 更清楚地表达了“我想移动一个元素”。

Go 1.21 引入 slices 包时,设计者已经很克制了:只加了最基础、最通用的函数。

Insert 和 Delete 入选了,因为它们覆盖了切片修改的常见模式。

Move 为什么没入选?可能就是因为 Alan 说的那个顾虑——怕开发者频繁在切片里移动元素,导致性能问题。

但这个提案告诉我们一个道理:工程实践的需求,有时会超过理论完美主义。

Move 不是让你处理百万级数据。它是让你在合适的场景下(小切片、UI 交互、排序调整),写出更清晰、更高效的代码。

我认为 slices.Move 应该被加入标准库。

理由有三:

  1. 填补 API 空缺:有 Delete、有 Insert,自然应该有 Move。
  2. 性能优势明显:一次内存移动 vs 两次,对重视性能的场景很实在。
  3. 代码可读性提升:slices.Move(s, from, to) 意图一目了然。

前面的担心不无道理,但 Go 的设计哲学里,“实用主义”一直是重要原则。切片在 Go 生态中的地位不可动摇,提供一个更高效的移动元素的方式,是对这种实用主义的延续。

这个提案的讨论区里,有一句评论我印象很深:

“Move 不是救世主,它是让你少写两行笨拙代码的语法糖。有时候,这就是标准库的职责。”

我觉得说得真好。

Go 以简洁著称,但简洁不等于简陋。当社区反复遇到同一个模式,标准库就有义务提供更好的原语。

slices.Move 不是什么革命性功能。但它能让你少写一次 Delete、少写一次 Insert,多一份代码清晰度,多一倍性能。

这,就值得加。

等这个提案通过后,我会回去重构那个 TODO 应用。把那三行笨代码,换成一行 slices.Move。然后告诉自己:这才是 Go 该有的样子。

相关文章
|
对象存储
如何设置对象存储OSS跨域(CORS)?
CORS的中文名是跨域资源共享,是HTML5提供的标准跨域解决方案。跨域访问,也叫JavaScript跨域访问问题,是浏览器出于安全考虑而设置的一个限制,即同源策略。当来自于A网站的页面中的JavaScript代码希望访问B网站的时候,浏览器会拒绝该访问,因为A、B两个网站是属于不同的域。
10009 0
|
4月前
|
人工智能 安全 芯片
OpenClaw免费安装教程,TopClaw零基础本地部署+1000万token领取
本文介绍TopClaw——一款专为小白设计的OpenClaw开源大模型“傻瓜式”本地部署工具。无需编程基础,Windows/Mac一键安装,中文界面友好,自带1000万免费token,全程离线运行,兼顾高效与隐私安全。
405 2
|
5月前
|
人工智能 自然语言处理 物联网
阿里云百炼大模型服务平台模型部署指南:流程与常见问题
阿里云百炼大模型部署流程参考,涵盖三种计费方式(预置吞吐PTU、模型单元、Token用量)的对比与适用场景,本文说明了各计费模式的费用计算、扩缩容规则及产品约束。部署后可通过OpenAI兼容接口、DashScope及Assistant SDK调用,并提供了代码示例。文章还解答了自有模型上传、权限不足、计费切换等常见问题。此外,2026年阿里云推出多项AI优惠:Qwen3.7-Max限时5折、HappyHorse视频模型8折、Token Plan多档套餐,以及轻量应用服务器38元/年起等云产品普惠权益,助力用户低成本落地AI应用。
|
10月前
|
存储 弹性计算 Linux
2026阿里云购买云服务器流程及注意事项(新用户指南)
在数字化场景中,个人和企业部署网站、APP 常需要服务器支撑。相比逐渐淘汰的虚拟主机和成本较高的独立服务器,云服务器凭借弹性扩展、性价比高的优势成为主流。阿里云 ECS(弹性计算服务)地域节点多、配置灵活,但新手容易在地域、实例规格等选择上困惑。下面结合最新信息,梳理阿里云服务器的购买流程和配置要点,帮新手高效完成选购。
|
5月前
|
人工智能
OPC中国和智能体来了是什么关系?
OPC中国是智能体来了旗下的开源人才生态平台,专注OPC一人公司与OPD一人部门的培育孵化;智能体来了则是AI智能体职业培训的能力底座。二者一体两面:前者重生态连接与场景落地,后者强专业训练与能力输出,共同构建“教—训—育—孵”闭环。
OPC中国和智能体来了是什么关系?
|
5月前
|
Web App开发 弹性计算 监控
tk矩阵系统自动化养号实战:Python脚本开发与阿里云部署指南
tk矩阵系统是跨境电商多账号高效管理的核心工具,其自动化养号能力直接决定账号存活率与运营效率。手动管理数十上百个账号不仅耗时耗力,还易因操作规律一致触发平台风控检测。本文基于Python与Selenium技术栈,系统讲解自动化养号脚本的完整开发流程,涵盖多账号隔离、真实行为模拟、设备指纹伪装、异常监控预警及阿里云ECS部署等核心模块,提供1700余行可直接运行的代码。本文仅用于技术学习交流,使用时请严格遵守平台用户协议与相关法律法规。
|
5月前
|
存储 人工智能 API
阿里云Token Plan 团队版支持使用优惠券吗?亲测可叠加优惠券,高级坐席可减30元,尊享坐席可减50元
阿里云百炼Token Plan团队版是一款以Credits统一计量的AI大模型订阅服务,支持文本与图像生成,兼容主流AI编程及智能体工具,提供标准(98元/坐席/月)、高级(698元/坐席/月)、尊享(1398元/坐席/月)三档坐席,额度从2.5万到25万Credits不等,并支持共享用量包弹性抵扣。用户可叠加使用618 AI加速季优惠券(个人最高减150元、企业最高减800元)及百炼"先用后返"券(最高返200元),企业迁云还可申请算力补贴,大幅降低团队AI应用落地成本。
|
5月前
|
Java API Go
阿里千问大模型API多语言对接实战:PHP/Java/.NET/Python/Go五栖开发指南
本文系统讲解了如何通过PHP、Java、.NET(C#)、Python、Go五种主流编程语言对接阿里云通义千问大模型API。从账号注册、服务开通、API Key获取等前置准备开始,详细阐述了DashScope原生SDK与OpenAI兼容接口两种调用方式。针对每种语言,均提供了完整的依赖安装、客户端初始化、单轮对话、多轮对话及流式输出的代码示例,并深入解析了请求参数、响应结构、错误处理等核心知识点。此外,文章还涵盖了WorkspaceId的配置方法、模型选型建议、RAM权限管理最佳实践以及成本优化策略,帮助开发者在不同技术栈下快速、安全地将千问大模型能力集成到实际业务中。
|
5月前
|
SQL 关系型数据库 MySQL
【第一阶段总结】MySQL基础20天 —— 知识地图与避坑复盘
本文是MySQL基础20天学习的系统复盘,涵盖架构、索引、SQL优化、事务、锁五大模块,提炼核心知识地图与高频避坑点(如无索引导致全表锁、RR下快照读与当前读差异等),并附面试考点与自测清单,助力夯实底层原理,平稳进阶。(239字)
329 1
|
7月前
|
人工智能 IDE 机器人
给阿里产品团队的真心话:千问很强,但我们需要它能“干活”!
作为一名一线程序员,建议千问尽快打通项目目录读取功能,并实现手机电脑端同步,做真正能干活的AI工具。