我在处理有关错误处理的例程和渠道方面遇到了一些麻烦。
首先,我有一个侦听消息的函数(在无限循环中):
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())
}
}
}
但是在DecodeMessage函数中,可能会出现多个错误。
func DecodeMessage(msg mqtt.Message, c1 chan MessageInfo) {
//do something, might result in error
//do another thing, might result in error
c1 <- MessageInfo{...}
}
通常我会从函数返回。但是对于惯例似乎有点棘手。我已查看this post,但如果两个错误都发生,我只会看到最后一条错误消息。
示例:
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,
...
}
}
我应该有某种数组并附加所有错误吗?在一个例程中出现多个错误是不好的做法吗?
对我来说,最好的事情是例程会在错误时退出并返回该错误,就像通常&#34;通常&#34;一样。这可能吗?
答案 0 :(得分:0)
我首先要说的是,即使失败也必须在返回之前对函数进行所有错误检查,这有点代码味道。 可能意味着你有一些奇怪的事情发生,并且可能有更好的方法来完成你想要做的事情。
但是,假设您已将问题归结为此问题,那么我会看到两个选项,具体取决于必须如何处理错误。
如果错误可以逐个处理并且并不真正相互依赖,那么您可以创建错误通道并在遇到错误时逐个发送它们。请参阅以下工作示例:
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\n", 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)
}
或者,如果您需要查看一次发生的所有错误(因为同时发生的两个错误可能表明某些特殊情况),那么您必须将它们全部附加到数组然后通过它们一个频道。请参阅以下工作示例:
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\n", 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)
}
答案 1 :(得分:0)
我可以看到返回多个错误很有用的情况,例如解析消息时有多个坏字段,需要将这些错误字段汇总回客户端。
我认为最好的方法是使用像hashicorp's multierror这样的包,它允许在实现错误接口的结构类型中使用格式化收集多个错误,因此仍然可以在chan error
上发送。然后,接收方可以仅处理标准错误,也可以提取有关每个错误的信息。
多恶意文档非常好,只需阅读github页面上的示例。
答案 2 :(得分:0)
对我来说,最好的事情是例程会因错误而退出 像往常一样返回那个错误&#34;通常&#34;。
当然,你可以,并获得最后一个错误或所有错误都很奇怪。
好的,现在回到原来的问题。考虑一下代码:
func foo(errTo chan error) {
defer close(errTo)
v, err := CouldFailOne()
if err != nil {
errTo <- err
return // Yp, just stop this routine, let it join back to Invoker
}
v2, err := CloudFailTwo()
if err != nil {
errTo <- err
return
}
// As the previous error handle until end of the function
}
如果要从此类函数返回值。只需使用一个频道,并将值发送到它只是没有错误提高。我认为这种风格会更加清晰,就像返回风格一样,只是使用了一个通道来返回错误。