douzhanjia0773 2018-04-25 18:50
浏览 22

处理来自单个通道的多个错误

I have some trouble with go routines and channels regarding error handling.

Firstly I have a function that listen for messages (in a infinite for loop):

func main() {

    messageChannel := make(chan messageHandler.MessageInfo)

    for {
        if token := client.Subscribe("#", 0, func(client MQTT.Client, msg MQTT.Message) {
            go messageHandler.DecodeMessage(msg, messageChannel)
            select {
            case messageInfo := <-messageChannel:
                //Handle
            }

        }); token.Wait() && token.Error() != nil {
            fmt.Println(token.Error())
        }
    }


}

But in the DecodeMessage function, there could arise multiple errors.

func DecodeMessage(msg mqtt.Message, c1 chan MessageInfo) {

    //do something, might result in error

    //do another thing, might result in error

    c1 <- MessageInfo{...}
}

Normally I would just return from the function. But seems a bit trickier with routines. I've looked at this post, but if both errors would occur, I would only see the last error message.

Example:

func DecodeMessage(msg mqtt.Message, c1 chan MessageInfo) {

    var returnError error

    if err != nil {
        returnError = err
    }

    if err != nil {
        returnError = err
    }

    c1 <- MessageInfo{
        Error: returnError,
        ...
    }
}

Should I have an array of some sort and append all errors? Is it bad practice to have multiple errors in one routine?

The best thing, for me, is that the routine would exit on an error and return that error like it would do "normally". Is that possible?

  • 写回答

3条回答 默认 最新

  • dpwqicw157673 2018-04-25 21:23
    关注

    I'll start by saying that having to go through all the error checks for a function before returning even if they fail is a bit of a code smell. It might mean that you have something weird going on and there may be a better way to accomplish what you're trying to do.

    However, assuming that you've boiled down your problem to this, then I see two options, depending on how the errors have to be handled.

    If the errors can be handled one-by-one and don't really rely on each other, then you can just create an error channel and send them back one by one as you encounter the errors. See the following working example:

    package main
    
    import (
        "errors"
        "fmt"
        "strings"
    )
    
    func main() {
        errCh := make(chan error)
        go HandleErrorsSerially("bad error", errCh)
        for err := range errCh {
            fmt.Printf("Found error serially: %v
    ", err)
        }
    }
    
    func HandleErrorsSerially(msg string, errCh chan<- error) {
        if strings.Contains(msg, "error") {
            errCh <- errors.New("message contained string 'error'")
        }
        if strings.Contains(msg, "bad") {
            errCh <- errors.New("message contained string 'bad'")
        }
        close(errCh)
    }
    

    Alternatively, if you need to have a view of all the errors that occurred all at once (because two errors happening simultaneously may indicate some special circumstances) then you'd have to append them all to an array and then pass them through a channel. See the following working example:

    package main
    
    import (
        "errors"
        "fmt"
        "strings"
    )
    
    func main() {
        errArrCh := make(chan []error)
        go HandleErrorsTogether("bad error", errArrCh)
        errArr := <-errArrCh
        fmt.Printf("Found the following errors together: %v
    ", errArr)
    }
    
    func HandleErrorsTogether(msg string, errArrCh chan<- []error) {
        errArr := make([]error, 0)
        if strings.Contains(msg, "error") {
            errArr = append(errArr, errors.New("message contained string 'error'"))
        }
        if strings.Contains(msg, "bad") {
            errArr = append(errArr, errors.New("message contained string 'bad'"))
        }
        errArrCh <- errArr
        close(errArrCh)
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 mmocr的训练错误,结果全为0
  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀