指针问题 之 range

本文探讨了Go语言使用range遍历指针时遇到的问题,分析了问题产生的原因,即range创建的局部变量引用的是切片拷贝的副本。提供了三种解决方案:将切片改为指针切片,通过索引获取值,或者在遍历时将引用变量的值赋给临时变量。

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

问题代码
package main

import "fmt"

type user struct {
	name string
	sex uint // 1 男 0 女
}

func main() {
	u := []user{
		{"Jansen",1},
		{"Lee",1},
		{"Leo Lee",0},
	}
	n := make([]*user,0,len(u))
	for _,v := range u{
		n = append(n, &v)
	}
	fmt.Println(n)
	for _,v := range n{
		fmt.Println(v)
	}
}
  • 输出
[0xc0000044c0 0xc0000044c0 0xc0000044c0]
&{Leo Lee 0}
&{Leo Lee 0}
&{Leo Lee 0}
问题分析
  • 用range声明的左变量v为局部变量,且仅被声明一次,变量v中的数据 切片u里成员的拷贝
  • 因此&v,拿到的仅仅是该局部变量的地址,且从声明到循环结束 v的地址一直没变
  • 切片遍历结束后,地址&v所存放的值是最后切片最后一个元素的值
  • 因此存放局部变量指针地址的n切片的遍历会有如上输出
解决方案一
  • 源切片改为指针切片
  • v的值本就是指针
package main

import "fmt"

type user struct {
	name string
	sex uint // 1 男 0 女
}

func main() {
	u := []*user{
		{"Jansen",1},
		{"Lee",1},
		{"Leo Lee",0},
	}
	n := make([]*user,0,len(u))
	for _,v := range u{
		n = append(n, v)
	}
	fmt.Println(n)
	for _,v := range n{
		fmt.Println(v)
	}
}
方案二
  • 拿索引取值
package main

import "fmt"

type user struct {
	name string
	sex uint // 1 男 0 女
}

func main() {
	u := []user{
		{"Jansen",1},
		{"Lee",1},
		{"Leo Lee",0},
	}
	n := make([]*user,0,len(u))
	for i,_ := range u{
		n = append(n, &u[i])
	}
	fmt.Println(n)
	for _,v := range n{
		fmt.Println(v)
	}
}
方案三
  • 把这个引用变量v的值倒一手,赋值给一个局部变量暂存
  • 防止next循环时,引用变量又变更
package main

import "fmt"

type user struct {
	name string
	sex uint // 1 男 0 女
}

func main() {
	u := []user{
		{"Jansen",1},
		{"Lee",1},
		{"Leo Lee",0},
	}
	n := make([]*user,0,len(u))
	for _,v := range u{
		_v := v
		n = append(n, &_v)
	}
	fmt.Println(n)
	for _,v := range n{
		fmt.Println(v)
	}
}

因此当你在遍历切片过程中修改数据,切记注意上述问题

package main

import "fmt"

type user struct {
	name string
	sex uint // 1 男 0 女
}

func main() {
	u := []user{
		{"Jansen",1},
		{"Lee",1},
		{"Leo Lee",0},
	}
	for i,_ := range u{
		u[i].sex = 0
	}
	fmt.Println(u)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JaysenLeo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值