在循环里开goroutine两种不同写法,结果不同

来源:15-3 提取城市和url

方目目

2019-10-01

老师,
engine/concurrent.go 文件的Run方法中,我写了一个和示例代码不同的开goroutine的方式,我的写法,会导致重复去Submit同一个url

    ##老师的写法,是在Submit方法里去开goroutine
    for _, r := range seeds {
		engine.Scheduler.Submit(r)
	}
	func (scheduler *SimpleScheduler) Submit(request engine.Request) {
		go func() {
			scheduler.c <- request
		}()
    }
	##我的写法,是在循环里直接开goroutine,
	for _, r := range seeds {
	    go func(){
	      engine.Scheduler.Submit(r)
	    }()
	}
	func (scheduler *SimpleScheduler) Submit(request engine.Request) {
			scheduler.c <- request
    }
	
写回答

1回答

ccmouse

2019-10-04

这里是一个for+goroutine常见的错误。
for _, r := range seeds
这句话里,r的生命周期是整个for,它的值依次为seeds里面的一个元素。循环结束的时候它就是seeds里的最后一个元素。
由于循环内部开了goroutine访问r,由于闭包的关系r一直不会销毁是seeds的最后一个元素。而这些所有的goroutine都访问了这个r,所以都是最后一个元素。
这里可以通过把r当作这个无名函数的参数的方法来强行拷贝r。
我们也可以运行go vet来检查出这个错误。

0
2
方目目
老师,我不太理解,ttps://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables 示例中的这种写法,也能正常运行 for i := range valslice { val := valslice[i] go func() { fmt.Println(val) }() }
2019-10-14
共2条回复

Google资深工程师深度讲解Go语言 由浅入深掌握Go语言

语法+分布式爬虫实战 为转型工程师量身打造

5995 学习 · 1909 问题

查看课程