Go 组合多个错误字符串
我是golang的新手,我的应用程序需要在一个循环中返回多个错误,之后需要合并并作为单个错误字符串返回。我无法使用字符串函数组合错误消息。在返回之前,可以使用哪些方法将这些错误合并为单个错误Go 组合多个错误字符串,go,error-handling,Go,Error Handling,我是golang的新手,我的应用程序需要在一个循环中返回多个错误,之后需要合并并作为单个错误字符串返回。我无法使用字符串函数组合错误消息。在返回之前,可以使用哪些方法将这些错误合并为单个错误 package main import ( "fmt" "strings" ) func Servreturn() (err error) { err1 = fmt.Errorf("Something else occured") err2 = fmt.Errorf("Some
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
}
字符串函数不处理错误,因为error实际上是实现函数error()字符串的接口 可以在err1.Error()和err2.Error()上使用字符串函数 但不是在“err1”引用本身上 有些错误是结构化的,比如从数据库驱动程序中得到的错误 所以在错误上使用字符串函数是不自然的,因为它们下面可能不是字符串 至于合并两个错误: 简单,只需再次使用fmt.Errorf
fmt.Errorf("Combined error: %v %v", err1, err2)
或者:
errors.New(err1.Error() + err2.Error())
要扩展@WillC在评论中提到的内容,可以将您自己的
error
类型定义为error
是一种接口类型。任何实现Error()字符串
函数的类型都实现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()string
时,它将迭代切片并创建一个串联的错误字符串
func main() {
collector := new(ErrorCollector)
for i := 0; i < 10; i++ {
collector.Collect(errors.New(fmt.Sprintf("%d Error", i)))
}
fmt.Println(collector)
}
func main(){
收集器:=新的(ErrorCollector)
对于i:=0;i<10;i++{
collector.Collect(errors.New(fmt.Sprintf(“%d Error”,i)))
}
fmt.Println(收集器)
}
有一个伟大的更详细的错误检查。上提供了该示例的完整示例。您可以使用
strings.Join()
和append()
函数来获取此片段
这将输出一个字符串,您可以将其发送回客户端
First error:server1
Second error:Package not installed
Third error:Socket is not connected
希望这有帮助 人们可能感兴趣的是,它将自己描述为“一个Go(golang)包,用于将错误列表表示为单个错误。”使用此功能:
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...)
}
当所有错误都为零时,它会给你零;当只有一个非零错误时,它会给你相同的错误;当有多个非零错误时,它会给你非零错误的编号列表
请在此处试用:Go 1.13的更新:
截止到,该语言现在直接支持
您可以使用fmt.Errorf
中的%w
动词包装错误:
err := errors.New("Original error")
err = fmt.Errorf("%w; Second error", err)
用于删除上次添加的错误,并返回剩余的内容:previousErrors:=errors.Unwrap(err)
另外两个函数,并提供检查和检索特定类型错误的方法
Dave Cheney出色的
错误
包()包括一个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)
时输出堆栈跟踪的选项
您可以在他的博客上找到关于该软件包的其他信息:和。优步有一个用于此用例的软件包:
返回多错误组合(err1,err2)
这似乎对我很有效(空格分隔错误):
除了使用fmt.Errorf()之外,还有其他方法吗?为什么我不能使用string函数?当然可以。这取决于你所说的“结合”的真正含义。字符串连接是使用
+
运算符完成的。或者您可以将它们单独存储在一个切片中,append()。这个问题建议你自己完成一个围棋教程,并获得一本关于它的书。@GregPetr另一个可能的干净方法是拥有自己的CombinedError
struct,它将错误列表作为字段,并实现Error()string
方法,然后执行你想要的操作,不管是串接字符串还是其他什么。没有足够的信息。客户做什么?你的服务器做什么?示例输出。谢谢,您的示例非常有用。我会尝试一下,然后回来。@BenCampbell这里有没有理由让方法接收器成为指针?谢谢你的提示。如果有可能添加一个nil错误,error()函数应该对收集的错误执行nil检查。如果只使用索引而不使用索引+值进行访问,则需要在索引访问之前强制转换错误数组。这里有一个例子:@Rakesh No.func(c*ErrorCollector)Error()(err string)
应该是func(c ErrorCollector)Error()(err string)
。包装不适用于多个错误。它用于用更多上下文包装一个错误。
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"
}
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)