私は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
}
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
お役に立てれば!
エラーは実際にはError()文字列関数を実装するインターフェイスであるため、文字列関数はエラーに対して機能しません。
Err1.Error()およびerr2.Error()で文字列関数を使用できますが、「err1」参照自体では使用できません。
一部のエラーは、データベースドライバーから取得するような構造体です。
そのため、エラーの文字列関数は実際にはその下にある文字列ではない可能性があるため、自然な方法はありません。
2つのエラーの結合に関して:
簡単です。もう一度fmt.Errorfを使用します。
fmt.Errorf("Combined error: %v %v", err1, err2)
代わりに:
errors.New(err1.Error() + err2.Error())
@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ブログ投稿 エラーについて詳しく説明しています。この例の完全な例は、 The Go Playground で入手できます。
https://github.com/hashicorp/go-multierror に興味があるかもしれません。これは、「エラーのリストを単一のエラーとして表すためのGo(golang)パッケージ」と記述されています。
Go 1.13の更新:
Goバージョン1.1 の時点で、言語の errorsパッケージ は error wrapping を直接サポートするようになりました。
_%w
_で_fmt.Errorf
_動詞を使用すると、エラーをラップできます。
_err := errors.New("Original error")
err = fmt.Errorf("%w; Second error", err)
_
nwrap を使用して、最後に追加されたエラーを削除し、残っているものを返します:previousErrors := errors.Unwrap(err)
さらに2つの関数 errors.Is および errors.As は、特定のタイプのエラーをチェックして取得する方法を提供します。
errors.Asおよびerrors.Isのプレイグラウンドの例
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)
を指定するときにスタックトレースを出力するオプションと同様に。
この機能を使用します。
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の場合はnil、nil以外のエラーが1つだけの場合は同じエラー、nil以外のエラーが複数ある場合はnil以外のエラーの番号付きリストが表示されます。
ここで試してみてください: https://play.golang.org/p/WttztCr-xHG