golang中关于range的坑

本文探讨了Go语言中处理切片和指针时遇到的一个常见误区。通过具体代码示例展示了循环中使用指针可能导致的问题,并解释了背后的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 arr1:=[]int{1,2,3}

arr2=make([]*int)

for _,v:=range arr1{

arr2=append(arr2,&v)}

for _,v:=range arr2{

fmt.Println(*v)}

执行以上代码,你会发现输出的全是3,本来我们预想的应该是1,2,3

为什么呢?

因为golang的range为了节省空间,每次v都是用了同样的地址,所以每次所取到的&v都是相同的,也就成了最后的3了

再比如下面这个例子

func main() {

   for i := 0; i < 10; i++ {
      fmt.Println(&i)
   }
}

执行后发现输出了10个相同的地址

<think>好的,用户想了解Golangrange关键字的用法,包括示例和解释。首先,我需要回忆一下Golangrange的各种常见用法,确保覆盖不同的数据结构,比如数组、切片、map、字符串和通道。然后,根据用户提供的引用资料,特别是引用2和3中的示例,需要详细说明这些用法,并指出需要注意的地方,比如值复制的问题。 首先,我应该分点说明range在不同数据结构中的应用。比如在数组和切片中,range返回索引和值;在map中返回键和值;在字符串中返回字符的索引和Unicode值;在通道中则用于迭代接收值直到关闭。同时,必须提到使用下划线_来忽略不需要的变量,比如忽略索引或键。 接下来,要注意用户提供的引用3中的示例,其中提到遍历数组时,v是复制后的值,修改它不会影响原数组。这一点需要特别强调,避免用户在使用时出现错误。此外,引用2中的三段式for循环和range结合的遍历方式也需要对比说明,突出range的简洁性。 然后,需要生成相关问题,这些问题应该围绕用户可能进一步感兴趣的点,比如range的底层机制、性能优化、与指针的结合使用、在并发中的安全性,以及与其他语言遍历语法的对比。这些问题能够帮助用户更深入地理解range的应用场景和注意事项。 最后,确保整个回答结构清晰,每个部分都有示例代码和解释,并且正确使用LaTeX格式,如变量名用$...$包裹。同时,引用用户提供的参考资料,在适当的位置添加引用标识,比如在说明值复制时引用[^3],在遍历map时引用[^2]。</think>### Golangrange关键字的用法解析 在Golang中,`range`是用于迭代数据结构(数组、切片、字符串、map、通道)的关键字,其行为根据数据结构类型有所不同。以下是具体用法和示例: --- #### 1. **数组/切片遍历** 语法:返回索引和值的副本 ```go arr := []int{10, 20, 30} for index, value := range arr { fmt.Printf("索引:%d 值:%d\n", index, value) } ``` - 示例说明:遍历时`value`是元素的副本,修改`value`不会影响原数组[^3] - 忽略索引:用`_`占位符 ```go for _, v := range arr { /* 仅用值 */ } ``` --- #### 2. **map遍历** 语法:返回键值对(无序) ```go m := map[string]int{"a": 1, "b": 2} for key, val := range m { fmt.Printf("键:%s 值:%d\n", key, val) } ``` - 注意:遍历顺序不固定,每次运行可能不同 --- #### 3. **字符串遍历** 语法:返回字符索引和Unicode值 ```go str := "Go语言" for i, r := range str { fmt.Printf("位置:%d Unicode码点:%U 字符:%c\n", i, r, r) } ``` - 注意:中文字符会占用多个字节,索引可能不连续 --- #### 4. **通道遍历** 语法:持续接收值直到通道关闭 ```go ch := make(chan int) go func() { ch <- 1 ch <- 2 close(ch) }() for v := range ch { fmt.Println("接收:", v) } ``` --- ### 关键注意事项 1. **值复制机制** 遍历时获取的是元素的副本,修改副本不影响原数据: ```go a := [3]int{1, 2, 3} for _, v := range a { v += 100 // 原数组保持[1,2,3] } ``` 若需修改原数据,需通过索引访问: ```go for i := range a { a[i] += 100 // 原数组变为[101,102,103] } ``` 2. **性能优化** 对大型数组建议使用索引直接访问,避免值复制的开销。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值