Go 语言 range 关键字全面解析

range 是 Go 语言中用于迭代数据结构的关键字,支持多种数据类型的遍历操作。它提供了一种简洁、安全且高效的方式来处理集合类型的数据。

基本语法

for index, value := range collection {// 循环体
}

1. 数组/切片迭代

fruits := []string{"Apple", "Banana", "Cherry"}// 只获取索引
for i := range fruits {fmt.Printf("Index: %d\n", i)
}// 只获取值
for _, fruit := range fruits {fmt.Printf("Fruit: %s\n", fruit)
}// 获取索引和值
for i, fruit := range fruits {fmt.Printf("%d: %s\n", i, fruit)
}

​输出​​:

Index: 0
Index: 1
Index: 2
Fruit: Apple
Fruit: Banana
Fruit: Cherry
0: Apple
1: Banana
2: Cherry

2. 映射(Map)迭代

ages := map[string]int{"Alice": 25,"Bob":   30,"Eve":   28,
}// 迭代键值对
for name, age := range ages {fmt.Printf("%s is %d years old\n", name, age)
}// 只迭代键
for name := range ages {fmt.Println("Name:", name)
}// 只迭代值
for _, age := range ages {fmt.Println("Age:", age)
}

​注意​​:映射的迭代顺序是不确定的,每次运行可能不同

3. 字符串迭代

str := "Go语言"// 按字节迭代(可能不完整处理Unicode字符)
for i, char := range []byte(str) {fmt.Printf("Byte %d: %d\n", i, char)
}// 正确方式:按Rune迭代(处理完整Unicode字符)
for i, char := range str {fmt.Printf("Rune %d: %c (Unicode: U+%04X)\n", i, char, char)
}// 统计字符串的Unicode字符数量
count := 0
for range str {count++
}
fmt.Printf("'%s' has %d runes\n", str, count) // "Go语言" has 4 runes

​输出​​:

Rune 0: G (Unicode: U+0047)
Rune 1: o (Unicode: U+006F)
Rune 2: 语 (Unicode: U+8BED)
Rune 5: 言 (Unicode: U+8A00)

4. 通道(Channel)迭代

func producer(ch chan<- int) {for i := 0; i < 3; i++ {ch <- i * 10}close(ch)
}func main() {ch := make(chan int, 3)go producer(ch)// 通道迭代直到关闭for value := range ch {fmt.Println("Received:", value)}
}

​输出​​:

Received: 0
Received: 10
Received: 20

5. 特殊数据结构迭代

a. 自定义类型迭代器

type IntRange struct {start, end int
}func (r *IntRange) Next() (int, bool) {if r.start >= r.end {return 0, false}value := r.startr.start++return value, true
}func (r *IntRange) Iterate() chan int {ch := make(chan int)go func() {defer close(ch)for value, ok := r.Next(); ok; value, ok = r.Next() {ch <- value}}()return ch
}func main() {r := &IntRange{start: 5, end: 8}for n := range r.Iterate() {fmt.Println(n) // 输出: 5,6,7}
}

b. 迭代空集合

var empty []int
for i, v := range empty {fmt.Println("This won't run")
}
// 安全,不会出错

6. 底层原理分析

range 实际上是一种语法糖,编译时会转换为普通循环:

// 原始代码
for i, v := range slice {// 操作
}// 编译后等效的代码
{tmpslice := slicefor i := 0; i < len(tmpslice); i++ {v := tmpslice[i]// 操作}
}

重要注意事项:

  1. ​值复制​​:range 迭代返回的是集合元素的​​副本​​,修改副本不影响原数据(指针/引用类型除外)
  2. ​指针处理​​:
    type Point struct{ X, Y int }points := []Point{{1, 2}, {3, 4}}for i, p := range points {// 修改副本不会影响原始数据p.X++ points[i].Y++ // 正确修改原数据的方式
    }

7. 性能优化技巧

a. 避免值复制

// 对于大结构体,避免复制开销
type BigStruct struct { data [1024]byte }bigSlice := make([]BigStruct, 1000)// 较差的方式:每次迭代复制整个结构体
for _, item := range bigSlice {// item 是副本
}// 推荐方式:按索引访问
for i := range bigSlice {// 直接操作 bigSlice[i]bigSlice[i].data[0] = 1
}

b. 避免内存分配

// 预分配切片用于结果收集
var results []int
data := []int{1, 2, 3, 4, 5}// 预分配空间
results = make([]int, 0, len(data))
for _, v := range data {results = append(results, v*2)
}

8. 常见问题与解决方案

问题1:修改原始切片失败

nums := []int{1, 2, 3}
for _, num := range nums {num *= 2 // 无效修改
}

​解决方案​​:使用索引

for i := range nums {nums[i] *= 2
}

问题2:goroutine 使用闭包陷阱

for i, v := range []int{10, 20, 30} {go func() {fmt.Println(i, v) // 所有goroutine输出相同的值}()
}

​解决方案​​:通过参数传递值

for i, v := range []int{10, 20, 30} {go func(i, v int) {fmt.Println(i, v) // 正确输出}(i, v)
}

9. 不同数据类型的特性总结

数据类型返回参数顺序保证修改影响
​数组​(index, value)顺序(0→N)副本修改无效
​切片​(index, value)顺序(0→N)副本修改无效
​映射​(key, value)随机副本修改无效
​字符串​(index, rune)顺序(0→N)不可修改
​通道​(value)发送顺序N/A

实际应用案例

1. 并行处理切片

func parallelProcess(data []int) []int {results := make([]int, len(data))var wg sync.WaitGroupwg.Add(len(data))for i, v := range data {go func(i, v int) {defer wg.Done()// 执行耗时操作results[i] = v * v}(i, v)}wg.Wait()return results
}

2. 并发安全迭代器

func safeIterate(m map[string]int) {// 创建临时副本迭代keys := make([]string, 0, len(m))for k := range m {keys = append(keys, k)}for _, k := range keys {v := m[k] // 安全访问// 处理逻辑}
}

3. 大型文件处理

func processLargeFile(filename string) {file, err := os.Open(filename)if err != nil {log.Fatal(err)}defer file.Close()scanner := bufio.NewScanner(file)for scanner.Scan() {line := scanner.Text()// 逐行处理大文件processLine(line)}if err := scanner.Err(); err != nil {log.Fatal(err)}
}

总结

Go 的 range 关键字是处理集合类数据的核心工具:

  1. ​简洁性​​:简化循环语法
  2. ​安全性​​:正确处理不同类型的边界情况
  3. ​高效性​​:编译优化后性能优秀
  4. ​灵活性​​:支持多数据类型和值选择

关键使用要点:

  • 理解不同数据类型的迭代特性
  • 注意值复制行为(尤其是大型结构体)
  • 在并发环境中安全使用
  • 利用索引优化性能

掌握 range 的深度使用可以极大提高 Go 编程的效率和代码质量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/84179.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/84179.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/84179.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

美化显示LLDB调试的数据结构

前面的博文美化显示GDB调试的数据结构介绍了如何美化显示GDB中调试的数据结构&#xff0c;本文将还是以mupdf库为例介绍如何美化显示LLDB中调试的数据结构。 先看一下美化后的效果&#xff1a; 一、加载自定义脚本 与GDB类似&#xff0c;需要添加一个~/.lldbinit文件&#xf…

【Java学习笔记】日期类

日期类 第一代日期类&#xff1a;Date 引入包 import java.text.ParseException&#xff1a;日期转换可能会抛出转换异常 import java.text.SimpleDateFormat import java.util.Date 1. 基本介绍 Date&#xff1a;精确到毫秒&#xff0c;代表特定的瞬间 SimpleDateForma…

C++基础进阶:函数、内联函数与Lambda函数详解

引言 在C编程的旅程中&#xff0c;函数是构建复杂程序的基本单元。它们像乐高积木一样&#xff0c;允许我们将代码分解成更小、更易于管理的部分。今天&#xff0c;我们将深入探讨C中的三种重要函数类型&#xff1a;普通函数、内联函数以及Lambda函数。掌握它们&#xff0c;将…

从Node.js到React/Vue3:流式输出技术的全栈实现指南

本文将从底层原理到工程实践&#xff0c;完整解析如何使用Node.js后端结合React和Vue3前端实现流式输出功能&#xff0c;涵盖协议选择、性能优化、错误处理等关键细节&#xff0c;并通过真实场景案例演示完整开发流程。 一、流式输出的核心原理与协议选择 1.1 流式传输的底层机…

AT2401C中科微2.4g芯片PA

作为无线通信系统的核心模块&#xff0c;射频前端芯片通过整合功率放大器&#xff08;PA&#xff09;、滤波器、开关和低噪声放大器&#xff08;LNA&#xff09;等关键组件&#xff0c;成为保障通信质量、降低功耗及维持信号稳定的决定性因素。 AT2401C是一款面向2.4GHz无线通信…

Linux安装jdk、tomcat

1、安装jdk sudo yum install -y java-1.8.0-openjdk-devel碰到的问题&#xff1a;/var/run/yum.pid 已被锁定 Another app is currently holding the yum lock&#xff1b; waiting for it to exit… https://blog.csdn.net/u013669912/article/details/131259156 参考&#…

在本地电脑中部署阿里 Qwen3 大模型及连接到 Elasticsearch

在今天的文章中&#xff0c;我将参考文章 “使用 Elastic 和 LM Studio 的 Herding Llama 3.1” 来部署 Qwen3 大模型。据测评&#xff0c;这是一个非常不错的大模型。我们今天尝试使用 LM Studio 来对它进行部署&#xff0c;并详细描述如何结合 Elasticsearch 来对它进行使用。…

【设计模式】2.策略模式

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 商场收银软件为例 1. 基础版 total 0def click_ok(price,num):tot price * numtotal totprint(合计&#xff1a;, total)增加打折 total 0def cli…

c++中的输入输出流(标准IO,文件IO,字符串IO)

目录 &#xff08;1&#xff09;I/O概述 I/O分类 不同I/O的继承关系 不同I/O对应的头文件 &#xff08;2&#xff09;iostream 标准I/O流 iostream头文件中的IO流对象 iostream头文件中重载了<<和>> 缓冲区示意图 标准输入流 cin用法 cin&#xff1a;按空…

人工智能学习06-循环

人工智能学习概述—快手视频 人工智能学习06-循环—快手视频

【电路】阻抗匹配

&#x1f4dd; 阻抗匹配 一、什么是阻抗匹配&#xff1f; 阻抗匹配&#xff08;Impedance Matching&#xff09;是指在电子系统中&#xff0c;为了实现最大功率传输或最小信号反射&#xff0c;使信号源、传输线与负载之间的阻抗达到一种“匹配”状态的技术。 研究对象&#x…

【vue】Uniapp 打包Android 文件选择上传问题详解~

需求 uniapp兼容android app&#xff0c;pc&#xff0c;h5的文件选择并上传功能。 需要支持拍照和相册选择&#xff0c;以及选择其他类型文件上传~ 实践过程和问题 开始使用uni-file-picker组件 以为很顺利&#xff0c;android模拟器测试…… 忽略了平台兼容性提示~&#…

Python:操作 Excel 格式化

🔧Python 操作 Excel 格式化完整指南(openpyxl 与 xlsxwriter 双方案) 在数据处理和报表自动化中,Python 是一把利器,尤其是配合 Excel 文件的读写与格式化处理。本篇将详细介绍两大主流库: openpyxl:适合读取与修改现有 Excel 文件xlsxwriter:适合创建新文件并进行复…

Prompt Enginering(提示工程)先进技术

前沿 CoT&#xff08;Chain-of-Thought&#xff09;和 ReACT&#xff08;Reasoning and Acting&#xff09;是两种先进的 Prompt Engineering&#xff08;提示工程&#xff09; 技术&#xff0c;旨在提升大语言模型&#xff08;LLM&#xff09;的推理、规划和执行能力。 CoT&a…

【C++系列】模板类型特例化

1. C模板类型特例化介绍 ​​定义​​&#xff1a;模板类型特例化&#xff08;Template Specialization&#xff09;是C中为模板的特定类型提供定制实现的机制&#xff0c;允许开发者对通用模板无法处理的特殊类型进行优化或特殊处理。 ​​产生标准​​&#xff1a; C98/03…

AI数据分析在体育中的应用:技术与实践

在现代体育竞技领域&#xff0c;"数据驱动"已不再是一个遥远的概念。尤其随着人工智能&#xff08;AI&#xff09;和大数据分析的不断成熟&#xff0c;从职业俱乐部到赛事直播平台&#xff0c;从运动员训练到球迷观赛体验&#xff0c;AI正以前所未有的方式渗透并改变…

计数思想-众数

11203-众数 题目描述(Description) 众数是指在一组数据中&#xff0c;出现次数最多的数。例如&#xff1a;1, 1, 3 中出现次数最多的数为 1&#xff0c;则众数为 1。 给定一组数&#xff0c;你能求出众数吗&#xff1f; 输入格式(Format Input) 第 1 行输入一个整数 n (1 &…

【Go语言基础【20】】Go的包与工程

文章目录 零、概述一、包基础1、包的核心作用2、包的声明与结构2.1、 包声明&#xff08;Package Declaration&#xff09;2.2、 包的目录结构&#xff08;工程视角&#xff09; 3、包的导入与调用3.1、导入包&#xff08;Import Packages&#xff09;3.2、 调用包成员3.3、 导…

《C++初阶之入门基础》【命名空间 + 输入输出 + 缺省参数 + 函数重载】

【命名空间 输入&输出 缺省参数 函数重载】目录 前言&#xff1a;---------------hello world---------------比较C语言和C的第一个程序&#xff1a;hello word ---------------命名空间---------------什么是命名空间&#xff1f;怎么使用命名空间&#xff1f;怎么定义…

java综合项目开发一课一得

文章目录 Java 综合项目课程学习&#xff1a;探索与成长之路一、课程初体验&#xff1a;从理论走向实践&#xff08;一&#xff09;系统学习 Java 核心理论知识&#xff08;二&#xff09;开启首个实践项目 —— 图书管理系统 二、项目攻坚&#xff1a;挑战与突破&#xff08;一…