Gre*_*etr 18 error-handling go
我是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
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*rth 18
字符串函数不能处理错误,因为错误实际上是一个实现函数Error()字符串的接口.
您可以在err1.Error()和err2.Error()上使用字符串函数,但不能在"err1"引用本身上使用.
有些错误是结构,比如从数据库驱动程序获得的结构.
所以没有自然的方法在错误上使用字符串函数,因为它们实际上可能不是字符串.
至于组合两个错误:
很简单,再次使用fmt.Errorf.
fmt.Errorf("Combined error: %v %v", err1, err2)
Run Code Online (Sandbox Code Playgroud)
或者:
errors.New(err1.Error() + err2.Error())
Run Code Online (Sandbox Code Playgroud)
Ina*_*mus 13
从 Go 1.20 开始,我们将能够使用Errors.Join包装多个错误。
请参阅此提案了解更多详细信息。
您可以打印错误;当您这样做时,它们将被换行符分隔。
var (
ErrIncorrectUsername = errors.New("incorrect username")
ErrIncorrectPassword = errors.New("incorrect password")
)
func main() {
err := validate("ruster", "4321")
// You can print multi-line errors
// Each will be separated by a newline character (\n).
if err != nil {
fmt.Println(err)
// incorrect username
// incorrect password
}
}
func validate(username, password string) error {
var errs []error
// errors.Join the errors into a single error
if username != "gopher" {
errs = append(errs, ErrIncorrectUsername)
}
if password != "1234" {
errs = append(errs, ErrIncorrectPassword)
}
// Join returns a single `error`.
// Underlying, the error contains all the errors we add.
return errors.Join(errs...)
}
Run Code Online (Sandbox Code Playgroud)
errors.Join返回一个error包含您添加的每个错误的错误。因此,您可以使用errors.Is和errors.As来检查单个错误以获得更细的粒度。
// ...
func main() {
err := validate("ruster", "4321")
// You can detect each one:
if errors.Is(err, ErrIncorrectUsername) {
// handle the error here
}
// Or detect the other one:
if errors.Is(err, ErrIncorrectPassword) {
// handle the error here
}
}
func validate(username, password string) error {
// ...
}
Run Code Online (Sandbox Code Playgroud)
注意:这个简单的validate例子是为了传达这个想法。不要将错误串联起来,而是将错误视为一棵树。Join与其他 s 结合使用时,您可以做到这一点Join。
ask*_*skb 10
你可以使用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")))
}
Run Code Online (Sandbox Code Playgroud)
这将输出一个字符串,您可以将其发送回客户端.
First error:server1
Second error:Package not installed
Third error:Socket is not connected
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!
为了扩展@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
}
Run Code Online (Sandbox Code Playgroud)
这提供了将给定值附加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)
}
Run Code Online (Sandbox Code Playgroud)
有一个很棒的golang.org博客文章详细介绍了错误。该示例的完整示例可在The Go Playground中找到。
人们可能对https://github.com/hashicorp/go-multierror感兴趣,它将自己描述为“一个 Go (golang) 包,用于将错误列表表示为单个错误。”。
Go 1.13的更新:
从Go版本1.13开始,该语言的错误包现在直接支持错误包装。
您可以在中使用%w动词来包装错误fmt.Errorf:
err := errors.New("Original error")
err = fmt.Errorf("%w; Second error", err)
Run Code Online (Sandbox Code Playgroud)
使用Unwrap删除最后添加的错误,并返回剩余的内容:previousErrors := errors.Unwrap(err)
另外两个功能是errors.is和errors.As提供检查和检索特定类型错误的方法。
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"
}
Run Code Online (Sandbox Code Playgroud)
这还允许其他功能,例如解包错误原因:
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"
}
Run Code Online (Sandbox Code Playgroud)
以及指定时输出堆栈跟踪的选项fmt.Printf("%+v\n", err)。
Uber为这个用例提供了一个multierr包:
return multierr.Combine(err1, err2)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18542 次 |
| 最近记录: |