以下是给我问题的代码。我要实现的是并行创建那些表。创建所有表后,我要退出功能。
func someFunction(){
....
gos := 5
proc := make(chan bool, gos)
allDone := make(chan bool)
for i:=0; i<gos; i++ {
go func() {
for j:=i; j<len(tables); j+=gos {
r, err := db.Exec(tables[j])
fmt.Println(r)
if err != nil {
methods.CheckErr(err, err.Error())
}
}
proc <- true
}()
}
go func() {
for i:=0; i<gos; i++{
<-proc
}
allDone <- true
}()
for {
select {
case <-allDone:
return
}
}
}
我正在创建两个 channel 1,以跟踪创建的表(proc)和其他的表(allDone)的数量,以查看是否全部完成。
当我运行此代码时,创建表的go例程开始执行,但在完成之前someFunction被终止。
但是,按顺序运行代码没有问题
我的设计模式有什么错误,以及如何纠正。
最佳答案
您尝试实现的通常模式使用 WaitGroup
。
我认为您面临的问题是,每个goroutine都会捕获i
,并且它会随着外循环的增加而不断增加。您的内部循环从i
开始,由于外部循环一直在继续,因此每个goroutine从5开始。
尝试将迭代器作为参数传递给goroutine,以便每次获得一个新副本。
func someFunction(){
....
gos := 5
var wg sync.WaitGroup
wg.Add(gos)
for i:=0; i< gos; i++ {
go func(n int) {
defer wg.Done()
for j:=n; j<len(tables); j+=gos {
r, err := db.Exec(tables[j])
fmt.Println(r)
if err != nil {
methods.CheckErr(err, err.Error())
}
}
}(i)
}
wg.Wait();
}
我不确定您要在这里实现什么,每个goroutine在开始的表上方的所有表上都执行
db.Exec
,因此第一个处理所有表,第二个处理除第一个表之外的所有表,依此类推。这是您想要的吗?