Goroutine 循环未完成
Goroutine loop not completing
我正在尝试遍历数组并复制数组中的每个值。我想在一个单独的 goroutine 中关闭每个循环。当我使用 goroutine 执行 运行 时,循环将比数组的大小少一个 (len(Array) -1),但是如果我摆脱 goroutine,那么它处理得很好。
我是否遗漏了一些关于它应该如何工作的信息? 运行ning goroutines 总是少一个,这似乎很奇怪。下面是我的代码。
func createEventsForEachWorkoutReference(plan *sharedstructs.Plan, user *sharedstructs.User, startTime time.Time, timeZoneKey *string, transactionID *string, monitoringChannel chan interface{}) {
//Set the activity type as these workouts are coming from plans
activityType := "workout"
for _, workoutReference := range plan.WorkoutReferences {
go func(workoutReference sharedstructs.WorkoutReference) {
workout, getWorkoutError := workout.GetWorkoutByName(workoutReference.WorkoutID.ID, *transactionID)
if getWorkoutError == nil && workout != nil {
//For each workout, create a reference to be inserted into the event
reference := sharedstructs.Reference{ID: workout.WorkoutID, Type: activityType, Index: 0}
referenceArray := make([]sharedstructs.Reference, 0)
referenceArray = append(referenceArray, reference)
event := sharedstructs.Event{
EventID: uuidhelper.GenerateUUID(),
Description: workout.Description,
Type: activityType,
UserID: user.UserID,
IsPublic: false,
References: referenceArray,
EventDateTime: startTime,
PlanID: plan.PlanID}
//Insert the Event into the databse, I don't handle errors intentionally as it will be async
creationError := eventdomain.CreateNewEvent(&event, transactionID)
if creationError != nil {
redFalconLogger.LogCritical("plan.createEventsForEachWorkoutReference() Error Creating a workout"+creationError.Error(), *transactionID)
}
//add to the outputchannel
monitoringChannel <- event
//Calculate the next start time for the next loop
startTime = calculateNextEventTime(&startTime, &workoutReference.RestTime, timeZoneKey, transactionID)
}
}(workoutReference)
}
return
}
经过更深入的研究,我认为我找到了根本原因,但还没有找到(优雅的)解决方案。
似乎正在发生的事情是,我的调用函数也在异步 goroutine 中 运行ning,并使用 "chan interface{}" 来监视进度并将进度流回客户端。在数组的最后一项上,它正在上游处理 chan 之前完成调用 goroutine。
等待通道处理完成的正确方法是什么。下面是我用来提供上下文的单元测试的一部分。
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
createEventsForEachWorkoutReference(plan, &returnedUser, startDate, &timeZone, &transactionID, monitoringChan)
}()
var userEventArrayList []sharedstructs.Event
go func() {
for result := range monitoringChan {
switch result.(type) {
case sharedstructs.Event:
counter++
event := result.(sharedstructs.Event)
userEventArrayList = append(userEventArrayList, event)
fmt.Println("Channel Picked Up New Event: " + event.EventID + " with counter " + strconv.Itoa(counter))
default:
fmt.Println("No Match")
}
}
}()
wg.Wait()
//I COULD SLEEP HERE BUT THAT SEEMS HACKY
close(monitoringChan)
想再添加一个示例(没有我的自定义代码)。您可以注释掉 sleep 行以查看它与 sleep 一起工作。
终于找到答案了...
问题是我需要在第一个 goroutine 中关闭我的 monitoringChan,然后在第二个 goroutine 中监视 (Defer wg.close())。我这样做的时候效果很好!
我正在尝试遍历数组并复制数组中的每个值。我想在一个单独的 goroutine 中关闭每个循环。当我使用 goroutine 执行 运行 时,循环将比数组的大小少一个 (len(Array) -1),但是如果我摆脱 goroutine,那么它处理得很好。
我是否遗漏了一些关于它应该如何工作的信息? 运行ning goroutines 总是少一个,这似乎很奇怪。下面是我的代码。
func createEventsForEachWorkoutReference(plan *sharedstructs.Plan, user *sharedstructs.User, startTime time.Time, timeZoneKey *string, transactionID *string, monitoringChannel chan interface{}) {
//Set the activity type as these workouts are coming from plans
activityType := "workout"
for _, workoutReference := range plan.WorkoutReferences {
go func(workoutReference sharedstructs.WorkoutReference) {
workout, getWorkoutError := workout.GetWorkoutByName(workoutReference.WorkoutID.ID, *transactionID)
if getWorkoutError == nil && workout != nil {
//For each workout, create a reference to be inserted into the event
reference := sharedstructs.Reference{ID: workout.WorkoutID, Type: activityType, Index: 0}
referenceArray := make([]sharedstructs.Reference, 0)
referenceArray = append(referenceArray, reference)
event := sharedstructs.Event{
EventID: uuidhelper.GenerateUUID(),
Description: workout.Description,
Type: activityType,
UserID: user.UserID,
IsPublic: false,
References: referenceArray,
EventDateTime: startTime,
PlanID: plan.PlanID}
//Insert the Event into the databse, I don't handle errors intentionally as it will be async
creationError := eventdomain.CreateNewEvent(&event, transactionID)
if creationError != nil {
redFalconLogger.LogCritical("plan.createEventsForEachWorkoutReference() Error Creating a workout"+creationError.Error(), *transactionID)
}
//add to the outputchannel
monitoringChannel <- event
//Calculate the next start time for the next loop
startTime = calculateNextEventTime(&startTime, &workoutReference.RestTime, timeZoneKey, transactionID)
}
}(workoutReference)
}
return
}
经过更深入的研究,我认为我找到了根本原因,但还没有找到(优雅的)解决方案。
似乎正在发生的事情是,我的调用函数也在异步 goroutine 中 运行ning,并使用 "chan interface{}" 来监视进度并将进度流回客户端。在数组的最后一项上,它正在上游处理 chan 之前完成调用 goroutine。
等待通道处理完成的正确方法是什么。下面是我用来提供上下文的单元测试的一部分。
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
createEventsForEachWorkoutReference(plan, &returnedUser, startDate, &timeZone, &transactionID, monitoringChan)
}()
var userEventArrayList []sharedstructs.Event
go func() {
for result := range monitoringChan {
switch result.(type) {
case sharedstructs.Event:
counter++
event := result.(sharedstructs.Event)
userEventArrayList = append(userEventArrayList, event)
fmt.Println("Channel Picked Up New Event: " + event.EventID + " with counter " + strconv.Itoa(counter))
default:
fmt.Println("No Match")
}
}
}()
wg.Wait()
//I COULD SLEEP HERE BUT THAT SEEMS HACKY
close(monitoringChan)
想再添加一个示例(没有我的自定义代码)。您可以注释掉 sleep 行以查看它与 sleep 一起工作。
终于找到答案了...
问题是我需要在第一个 goroutine 中关闭我的 monitoringChan,然后在第二个 goroutine 中监视 (Defer wg.close())。我这样做的时候效果很好!