转投go系列-for循环出错问题

  • for循环错误反例:
func main() {
	in := []int{1, 2, 3, 4, 5}
	out := make([]*int, 0)
	for _, v := range in {
		//v := v  打开注释即正确
		out = append(out, &v)
	}

	fmt.Println("res:", *out[0], *out[1], *out[2])
}

期望结果:1,2,3
实际结果:5,5,5
原因:range出来的v是同一个地址,最后都指向了5
解决方案:打开注释,分配新地址再赋值

  • for循环错误反例2:
package main

import (
	"fmt"
	"sync"
)

func main() {
	var mutex sync.Mutex
	type ABC struct {
		Aa int
	}
	persons := make([]ABC, 10)
	for i, p := range persons {
		mutex.Lock()
		defer mutex.Unlock()
		p.Aa = 2
		fmt.Println("count:", i)
	}
}

大家会习惯在上锁后直接defer解锁,如果defer写到了for里面,运行就会出错啦。fatal error: all goroutines are asleep - deadlock!
两种解决方案,一种for里面不要用defer。另一种可以for里面设计个匿名函数,如下:

package main

import (
	"fmt"
	"sync"
)

func main() {
	var mutex sync.Mutex
	type ABC struct {
		Aa int
	}
	persons := make([]ABC, 10)
	for i, p := range persons {
		func() {
			mutex.Lock()
			defer mutex.Unlock()
			p.Aa = 2
			fmt.Println("count:", i)
		}()
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值