请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于parsecity的string(m[2])和name=string(m[2])的疑问

关于parsecity解析的时候,string(m[2)必须赋值为name=string(m[2)的疑问
老师您好!在单任务爬虫最后一节那里,每个城市列表里的用户信息,用闭包把上一级的用户名称带入到profile里面,为什么用string(m[2)就会导致所有人的姓名全部显示为第一个人的名称,
而用name=string(m[2) 就不会呢?
我理解是循环结束后,从request列表里拿出return profile(url,string(m[2) 和return profile(url,name)
不都是把m[2]的数值存储进去了吗?如果string(m[2]) 无法存储,为什么name就可以?
此处没太明白,为什么一个循环共用了第一个M[2]?
这块想了好几天没想明白?

正在回答

1回答

这的确是go函数式编程的一个坑。我们这里:

https://img1.sycdn.imooc.com//szimg/5e132c4d09f189f209760360.jpg

这个ParserFunc的值是一个函数,这个函数引用了m[2]。这个m[2]的值什么时候去拿呢?不是现在,是这个ParserFunc被执行的时候,也就是这个对应的Profile的页面被拉下来,送到Profile页面的Parser里面的时候,才被计算。这时,这里的for早就跑完了。go语言中这个for _, m := range matches的m的生命周期并不是一个循环节,而是整个循环的过程中,始终只有一个m,每次进入for的一个循环节,就把下一个matches里的元素赋值给m。那么这些循环全部跑完,m的值是多少呢?答案是最后一个matches的元素。而这个ParserFunc在真正运行的时候,早已在这个循环跑完之后,因此所有的m[2]这里都是最后一个匹配。

反过来,用了name:=m[2],或者上面一行Url:string(m[1]),为什么可以呢?因为这两行运行的时机是循环体内,拿出第一个m,立刻就计算,m[1]是多少,m[2]是多少,分别赋值给其它变量。注意这里的name是循环节内定义的,它的生命周期是这个循环节内,每一此循环都会生出一个不同的name,而m一共只有一个。

我写了一个简单的演示:https://play.studygolang.com/p/7o0QWZhq6eb

结论:这行代码是立刻执行的,用m没问题。如果不是,那要拷贝一份出来再引用,因为那个m会被重复利用。

2 回复 有任何疑惑可以回复我~
  • 提问者 慕用7464701 #1
    多谢老师的指导
    回复 有任何疑惑可以回复我~ 2020-01-11 15:12:00
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信