我是Golang的新手,我的应用程序需要在循环中返回多个错误,以后需要组合并作为单个错误字符串返回。我无法使用字符串函数来组合错误消息。在返回之前,可以使用哪些方法将这些错误组合成单个错误?
package main
import (
"fmt"
"strings"
)
func Servreturn() (err error) {
err1 = fmt.Errorf("Something else occured")
err2 = fmt.Errorf("Something else occured again")
// concatenate both the error
return err3
}
答案 0 :(得分:14)
字符串函数不会处理错误,因为错误实际上是一个实现函数Error()字符串的接口。
你可以在err1.Error()和err2.Error()上使用字符串函数 但不是" err1"引用自己。
某些错误是结构,就像您从数据库驱动程序获得的那样。
因此,在错误中使用字符串函数是不自然的,因为它们实际上可能不是字符串。
至于组合两个错误:
很简单,只需再次使用fmt.Errorf。
fmt.Errorf("Combined error: %v %v", err1, err2)
可替换地:
errors.New(err1.Error() + err2.Error())
答案 1 :(得分:9)
您可以使用strings.Join()
和append()
函数来实现此切片。
package main
import (
"fmt"
"strings"
"syscall"
)
func main() {
// create a slice for the errors
var errstrings []string
// first error
err1 := fmt.Errorf("First error:server error")
errstrings = append(errstrings, err1.Error())
// do something
err2 := fmt.Errorf("Second error:%s", syscall.ENOPKG.Error())
errstrings = append(errstrings, err2.Error())
// do something else
err3 := fmt.Errorf("Third error:%s", syscall.ENOTCONN.Error())
errstrings = append(errstrings, err3.Error())
// combine and print all the error
fmt.Println(fmt.Errorf(strings.Join(errstrings, "\n")))
}
这将输出一个字符串,您可以将其发送回客户端。
First error:server1
Second error:Package not installed
Third error:Socket is not connected
希望这有帮助!
答案 2 :(得分:5)
对于这种用例,Uber有一个multierr包:
return multierr.Combine(err1, err2)
答案 3 :(得分:4)
为了扩展@WillC在评论中提到的内容,可以定义自己的error
类型,因为error
是一种接口类型。任何实现Error() string
函数的类型都会实现error
接口。因此,您可以创建一个聚合错误的CollectionError
并返回一个连接的错误字符串。
type ErrorCollector []error
func (c *ErrorCollector) Collect(e error) { *c = append(*c, e) }
func (c *ErrorCollector) Error() (err string) {
err = "Collected errors:\n"
for i, e := range *c {
err += fmt.Sprintf("\tError %d: %s\n", i, e.Error())
}
return err
}
这提供了一个将给定error
附加到切片的集合函数。在调用Error() string
时,它会迭代切片并创建一个连接的错误字符串。
func main() {
collector := new(ErrorCollector)
for i := 0; i < 10; i++ {
collector.Collect(errors.New(fmt.Sprintf("%d Error", i)))
}
fmt.Println(collector)
}
有一个很好的golang.org blog post更详细的错误。 The Go Playground上提供了该示例的完整示例。
答案 4 :(得分:2)
人们可能会对https://github.com/hashicorp/go-multierror感兴趣,它将自己描述为“用于将错误列表表示为单个错误的A Go(golang)包。”。
答案 5 :(得分:2)
Dave Cheney出色的errors
软件包(https://github.com/pkg/errors)包括一个Wrap
函数,用于此目的:
package main
import "fmt"
import "github.com/pkg/errors"
func main() {
err := errors.New("error")
err = errors.Wrap(err, "open failed")
err = errors.Wrap(err, "read config failed")
fmt.Println(err) // "read config failed: open failed: error"
}
这还允许其他功能,例如解包错误原因:
package main
import "fmt"
import "github.com/pkg/errors"
func main() {
err := errors.New("original error")
err = errors.Wrap(err, "now this")
fmt.Println(errors.Cause(err)) // "original error"
}
以及指定fmt.Printf("%+v\n", err)
时输出堆栈跟踪的选项。
答案 6 :(得分:1)
这对我来说似乎很好(空格错误):
var errors []error
errors = append(errors, fmt.Errorf("error 1"))
errors = append(errors, fmt.Errorf("error 2"))
errors = append(errors, fmt.Errorf("and yet another error"))
s := fmt.Sprintf("%s", errors)
fmt.Println(s)
答案 7 :(得分:0)
使用此功能:
func JoinErrs(errs ...error) error {
var joinErrsR func(string, int, ...error) error
joinErrsR = func(soFar string, count int, errs ...error) error {
if len(errs) == 0 {
if count == 0 {
return nil
}
return fmt.Errorf(soFar)
}
current := errs[0]
next := errs[1:]
if current == nil {
return joinErrsR(soFar, count, next...)
}
count++
if count == 1 {
return joinErrsR(fmt.Sprintf("%s", current), count, next...)
} else if count == 2 {
return joinErrsR(fmt.Sprintf("1: %s\n2: %s", soFar, current), count, next...)
}
return joinErrsR(fmt.Sprintf("%s\n%d: %s", soFar, count, current), count, next...)
}
return joinErrsR("", 0, errs...)
}
当所有错误都为零时,它会给你nil,当只有一个非零错误时会给你同样的错误,当多个非零错误时会给你编号的非零错误列表