为了让大家更好的理解本期知识点,先介绍以下几个知识点:线性结构、非线性结构、循环、迭代、遍历、递归。
创新互联公司成都网站建设按需定制设计,是成都网站制作公司,为成都LED显示屏提供网站建设服务,有成熟的网站定制合作流程,提供网站定制设计服务:原型图制作、网站创意设计、前端HTML5制作、后台程序开发等。成都网站推广热线:028-86922220
下面会挑选几个经典的案例,一块来探讨下,看看如何避免掉坑,多积累积累采坑经验。
先来到开胃菜,热热身~
type student struct {
name string
age int
}
func main() {
m := make(map[string]student)
stus := []student{
{name: "张三", age: 18},
{name: "李四", age: 23},
{name: "王五", age: 26},
}
for _, stu := range stus {
m[stu.name] = stu
}
for k, v := range m {
fmt.Println(k, "=>", v.name)
}
}
不出意料,输出结果为:
李四 => 李四
王五 => 王五
张三 => 张三
这题比较简单,就是简单的传值操作,大家应该都能答上来。下面加大难度,改为传址操作
将案例一改为传址操作
type student struct {
name string
age int
}
func main() {
m := make(map[string]*student)
stus := []student{
{name: "张三", age: 18},
{name: "李四", age: 23},
{name: "王五", age: 26},
}
for _, stu := range stus {
m[stu.name] = &stu
}
for k, v := range m {
fmt.Println(k, "=>", v.name)
}
}
好好想想应该输出什么结果呢?还是跟案例一是一样的结果吗?难道会有坑?
不出意料,还是出了意外,输出结果为:
张三 => 王五
李四 => 王五
王五 => 王五
为什么呢?
解决方案:
在for循环中,做同名变量覆盖stu:=stu(即重新声明一个局部变量,做值拷贝,避免相互影响)
type student struct {
name string
age int
}
func main() {
m := make(map[string]*student)
stus := []student{
{name: "张三", age: 18},
{name: "李四", age: 23},
{name: "王五", age: 26},
}
for _, stu := range stus {
stu := stu //同名变量覆盖
m[stu.name] = &stu
}
for k, v := range m {
fmt.Println(k, "=>", v.name)
}
}
输出结果:
张三 => 张三
李四 => 李四
王五 => 王五
在for循环里,做闭包操作,也是很容易掉坑的。看看下面输出什么?
var prints []func()
for _, v := range []int{1, 2, 3} {
prints = append(prints, func() { fmt.Println(v) })
}
for _, print := range prints {
print()
}
一眼看过去,感觉是输出1 2 3,但实际会输出 3 3 3
为什么呢?
解决方案:
和案例二解决方案一样,是在for循环中,做同名变量覆盖v:=v
var prints []func()
for _, v := range []int{1, 2, 3} {
v := v //同名变量覆盖
prints = append(prints, func() { fmt.Println(v) })
}
for _, print := range prints {
print()
}
输出结果:
1
2
3
在for循环里,起goroutine协程,也是很迷惑很容易掉坑的。看看下面输出什么?
var wg sync.WaitGroup
strs := []string{"1", "2", "3", "4", "5"}
for _, str := range strs {
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println(str)
}()
}
wg.Wait()
一眼看过去,感觉是会无序输出1 2 3 4 5,但实际会输出 5 5 5 5 5
为什么呢?
解决方案:
和前面两个案例解决方案一样,是在for循环中,做同名变量覆盖str:=str
var wg sync.WaitGroup
strs := []string{"1", "2", "3", "4", "5"}
for _, str := range strs {
str := str //同名变量覆盖
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println(str)
}()
}
wg.Wait()
输出结果:
5
4
2
1
3
注意是1~5无序输出
for循环中做传址、闭包、goroutine相关操作,千万要注意,一不小心就会很容易掉坑。
使用好同名变量覆盖v:=v,这个解决大法,能很便捷的解决这一类问题。
本文转载自微信公众号「 程序员升级打怪之旅」,作者「王中阳Go」,可以通过以下二维码关注。
转载本文请联系「 程序员升级打怪之旅」公众号。
网站名称:Goforrange一不小心就掉坑里了
URL网址:http://www.csdahua.cn/qtweb/news11/8611.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网