golang在遍历slice中的坑

本文探讨了Go语言中Map与Slice结合使用时的常见陷阱,通过具体代码示例展示了错误的用法可能导致的问题,并提供了正确的解决方案。文章强调了在处理结构体切片并将其元素作为Map的值时,应正确引用切片中的每个元素,避免所有Map值指向同一内存地址。
package main

import "fmt"

func main() {
	pase_student()
}

type student struct {
	Name string
	Age  int
}

func pase_student() {
	m := make(map[string]*student)
	stus := []student{
		{Name: "zhou", Age: 24},
		{Name: "li", Age: 23},
		{Name: "wang", Age: 22},
	}
	for _, stu := range stus {
		m[stu.Name] = &stu // 将临时变量stu的地址给map,最后所有的地址都为同样的一个值
	}

	for k, v := range m {
		fmt.Println(k, v)
	}
}

所以这种使用是有问题的

 

应该改为

package main

import "fmt"

func main() {
	pase_student()
}

type student struct {
	Name string
	Age  int
}

func pase_student() {
	m := make(map[string]*student)
	stus := []student{
		{Name: "zhou", Age: 24},
		{Name: "li", Age: 23},
		{Name: "wang", Age: 22},
	}
	for i, v := range stus {
		m[v.Name] = &stus[i] 
	}

	for k, v := range m {
		fmt.Println(k, v)
	}
}

在Go语言中,不同类型对象的遍历赋值方法有所不同,以下为几种常见对象的遍历赋值方法: ### 数组遍历赋值 数组声明和赋值可以使用 `var arrayName = [N]type{value1, value2, value3……}` 的语法。若要遍历数组并赋值,可使用索引来访问数组元素并进行赋值操作。示例代码如下: ```go package main import "fmt" func main() { // 声明并初始化一个长度为3的字符串数组 var names = [3]string{"", "", ""} fmt.Printf("变量 names 类型为:%T\n", names) fmt.Printf("打印结果:%v\n", names) fmt.Printf("长度为:%d\n", len(names)) // 遍历数组并赋值 for i := range names { names[i] = fmt.Sprintf("name%d", i+1) } fmt.Printf("赋值结果:%v\n", names) } ``` 这样便实现了数组的遍历赋值,这里主要利用了数组的索引进行操作 [^3]。 ### 列表(双向链表)遍历与元素操作 Go语言中的 `list` 是双向链表实现,能高效地进行任意位置的元素插入和删除操作。若要对 `list` 进行遍历赋值,可使用其提供的方法。示例代码如下: ```go package main import ( "container/list" "fmt" ) func main() { // 声明一个list l := list.New() // 向list中添加元素 l.PushBack(1) l.PushBack(2) l.PushBack(3) // 遍历list并修改元素值 for e := l.Front(); e != nil; e = e.Next() { // 假设将每个元素的值乘以2 e.Value = e.Value.(int) * 2 } // 再次遍历list并打印元素值 for e := l.Front(); e != nil; e = e.Next() { fmt.Println(e.Value) } } ``` 此代码先创建了一个 `list` 并添加元素,接着遍历 `list` 对元素值进行修改,最后再次遍历打印修改后的值 [^1]。 ### 自定义结构体切片遍历赋值 对于自定义结构体切片,可在遍历过程中创建新的结构体实例并赋值给切片元素。示例代码如下: ```go package main import "fmt" // 定义一个结构体 type T struct { a int b int } func main() { // 假设存在一个list list := []T{ {a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}, } // 遍历之前先new个固定长度的slice出来,然后用数组的索引赋值 rst := make([]*T, len(list)) for i := range list { v := &T{ a: list[i].a + 1, b: list[i].b, } rst[i] = v } // 打印结果 for _, v := range rst { fmt.Printf("a: %d, b: %d\n", v.a, v.b) } } ``` 该代码定义了一个结构体 `T`,创建了一个 `T` 类型的切片 `list`,接着遍历 `list`,创建新的 `T` 结构体实例并赋值给 `rst` 切片,最后打印 `rst` 切片中元素的值 [^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值