@nil 正好,先别跑。请教个问题 :pensive_party_blob:

为什么 for循环里打印的是123(说明传递给worker的参数是123吧),但到goroutine函数里面就不固定了?

@nil 好。我在for range前面打印了下id,的确是123。

似乎加上了for range(channel)才令情况复杂起来的

@meina 我这里图片还没显示出来,真让人捉急。。
不过文章应该很好的说明了你遇到的这个问题

The val variable in the above loops is actually a single variable that takes on the value of each slice element. Because the closures are all only bound to that one variable, there is a very good chance that when you run this code you will see the last element printed for every iteration instead of each value in sequence, because the goroutines will probably not begin executing until after the loop.

刚看完这篇文章。不是这个问题 

@nil

可以在这里在线运行: play.golang.org/

package main

import (
"fmt"
"time"
)

func worker(id int, jobs <-chan int) {
fmt.Println("id",id)
for j := range jobs {
fmt.Println("worker", id, "started job", j)
//time.Sleep(time.Second)
}
}

func main() {

const numJobs = 5
jobs := make(chan int, numJobs)

for w := 1; w <= 3; w++ {
fmt.Println("id: ", w)
go worker(w, jobs)
}

for j := 1; j <= numJobs; j++ {
jobs <- j
}
close(jobs)

time.Sleep(time.Second * 4)
}

@nil 多运行两次。然后观察打印的
fmt.Println("worker", id, "started job", j)
中的id

就很怪异。

@meina 怪异的id的原因就是文中提到的这个问题啊

@nil 似乎不太一样。
文中遍历的是普通变量。而我这个情况其实是遍历channel。

另一个朋友给了一个解释,我觉得能说通:并行读取chan变量时,顺序不固定。而上面那个for-range jobs就是这种情况。

改造了下,这个例子能证明上面的解释。
for j := 1; j <= numJobs; j++ {
jobs <- j
}

for i :=1; i<=5; i++{
go func() {
fmt.Println("jobs:", <- jobs)
}()
}

@meina 其实是一样的问题,并行读取w和job时,顺序都是只有god知道,channel只是让这个问题更云里雾里了而已
你得先理解了go worker() 这里并发执行的机理,不要拿单进程的循环思路来理解并发

Follow

@meina 还有个问题,一般我写for循环,都会写成
for i:=0; i<n; i++ 的形式,很少写
for i:=1; i<=n; i++
就像go的切片一样,会写成包含开始不包含结束的形式,除非一些特殊需求,这适用于所有语言

@nil 明白。我也是习惯从0开始,刚刚算是偶然。 :pensive_party_blob:

Sign in to participate in the conversation
Qoto Mastodon

QOTO: Question Others to Teach Ourselves
An inclusive, Academic Freedom, instance
All cultures welcome.
Hate speech and harassment strictly forbidden.