代码之家  ›  专栏  ›  技术社区  ›  mornindew

高朗昌在调查结果时被吊死了

  •  0
  • mornindew  · 技术社区  · 6 年前

    我对歌朗频道还很陌生,但它并不像我想象的那样运作。

    wg.Wait() 完成。

    不幸的是,当循环通过成龙的结果将挂起。我假设,因为它仍然在等待成龙得到填补,但不是所有的goroutine都会抛出错误。

    处理不总是填充的通道循环的最佳方法是什么?我也知道我不必在这里使用CHANs,但我想确保我理解它们。

    下面是我的代码。

    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
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   mornindew    6 年前

    所以,在发布后不久,我就想出了一个解决办法。我的问题有两个方面:

    1. 关闭我的频道以便它知道何时停止收听
    2. 使用不一致的方法将数据从goroutine获取到调用函数。对于使用chan的错误,但对于自定义结构,我只是设置它。我将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"}
        }
    
        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
    }