我对GoLang频道还很陌生,但效果不如预期。
我有一个函数,我想调用3个独立的goroutine,然后等待它们全部完成。如果出现错误,则尝试将其放在CHAN上,然后在wg.Wait()
完成后处理该错误。
不幸的是,当循环遍历CHAN结果时,它将挂起。我推测是因为它仍在等待CHAN填充,但并非所有goroutine都会抛出错误。
处理不总是填充的通道的最佳方法是什么?我也知道我不必在这里使用CHAN,但是我想确保我理解它们。
下面是我的代码。
func createWorkoutPlanForUserPreconditionCheck(planID, userID, transactionID *string) (*sharedstructs.Plan, *sharedstructs.User, *sharedstructs.Profile, error) {
if planID == nil || userID == nil || transactionID == nil {
return nil, nil, nil, sharedstructs.InvalidData{Msg: "Cannot pass in Nil Parameters"}
}
plan := sharedstructs.Plan{}
user := sharedstructs.User{}
profile := sharedstructs.Profile{}
//myError := sharedstructs.InvalidData{}
ch := make(chan sharedstructs.InvalidData, 3)
var wg sync.WaitGroup
wg.Add(3)
//Get the Plan from the Plan ID
go func() {
defer wg.Done()
returnedPlan, readError := readPlan(*planID)
if readError != nil || returnedPlan == nil {
ch <- sharedstructs.InvalidData{Msg: "Could Not Retreive the User with ID: " + *userID}
} else {
plan = *returnedPlan
}
}()
//Get the User
go func() {
defer wg.Done()
returnedUser, getUserError := userdomain.GetUserByID(*userID, *transactionID)
if getUserError != nil || &returnedUser == nil {
ch <- sharedstructs.InvalidData{Msg: "Could Not Retreive the User with ID: " + *userID}
} else {
user = returnedUser
}
}()
//Get the Profile
go func() {
defer wg.Done()
readProfile, getProfileError := profiledomain.GetProfile(*userID, *transactionID)
if getProfileError != nil || readProfile == nil {
ch <- sharedstructs.InvalidData{Msg: "Could Not Retreive the User with ID: " + *userID}
} else {
profile = *readProfile
}
}()
wg.Wait()
////"Hangs Here" - PUT MY ERROR HANDLING LOGIC HERE
for err := range ch {
fmt.Println(err.Error())
}
return &plan, &user, &profile, nil
}
答案 0 :(得分:1)
因此,发布后不久我就找到了解决方案。我的问题实际上有两个方面:
^^^解决这些问题使我的代码正常工作,但这就是我的代码最终的结果。
func createWorkoutPlanForUserPreconditionCheck(planID, userID, transactionID *string) (*sharedstructs.Plan, *sharedstructs.User, *sharedstructs.Profile, error) {
if planID == nil || userID == nil || transactionID == nil {
return nil, nil, nil, sharedstructs.InvalidData{Msg: "Cannot pass in Nil Parameters"}
}
outputChannel := make(chan interface{}, 3)
var wg sync.WaitGroup
wg.Add(3)
//Get the Plan from the Plan ID
go func() {
defer wg.Done()
returnedPlan, readError := readPlan(*planID)
if readError != nil || returnedPlan == nil {
outputChannel <- sharedstructs.InvalidData{Msg: "Could Not Retreive the User with ID: " + *userID}
} else {
outputChannel <- *returnedPlan
}
}()
//Get the User
go func() {
defer wg.Done()
returnedUser, getUserError := userdomain.GetUserByID(*userID, *transactionID)
if getUserError != nil || &returnedUser == nil {
outputChannel <- sharedstructs.InvalidData{Msg: "Could Not Retreive the User with ID: " + *userID}
} else {
outputChannel <- returnedUser
}
}()
//Get the Profile
go func() {
defer wg.Done()
readProfile, getProfileError := profiledomain.GetProfile(*userID, *transactionID)
if getProfileError != nil || readProfile == nil {
outputChannel <- sharedstructs.InvalidData{Msg: "Could Not Retreive the User with ID: " + *userID}
} else {
outputChannel <- *readProfile
}
}()
wg.Wait()
close(outputChannel)
plan := sharedstructs.Plan{}
user := sharedstructs.User{}
profile := sharedstructs.Profile{}
for result := range outputChannel {
switch result.(type) {
case sharedstructs.InvalidData:
return nil, nil, nil, result.(sharedstructs.InvalidData)
case sharedstructs.Plan:
plan = result.(sharedstructs.Plan)
case sharedstructs.User:
user = result.(sharedstructs.User)
case sharedstructs.Profile:
profile = result.(sharedstructs.Profile)
}
}
return &plan, &user, &profile, nil
}