web-dev-qa-db-ja.com

複数のエラー文字列を組み合わせる

私は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

}
16
Greg Petr

strings.Join()およびappend()関数を使用して、このスライスを実現できます。

例:golang playgorund

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

お役に立てれば!

10
askb

エラーは実際にはError()文字列関数を実装するインターフェイスであるため、文字列関数はエラーに対して機能しません。

Err1.Error()およびerr2.Error()で文字列関数を使用できますが、「err1」参照自体では使用できません。

一部のエラーは、データベースドライバーから取得するような構造体です。

そのため、エラーの文字列関数は実際にはその下にある文字列ではない可能性があるため、自然な方法はありません。

2つのエラーの結合に関して:

簡単です。もう一度fmt.Errorfを使用します。

fmt.Errorf("Combined error: %v %v", err1, err2)

代わりに:

errors.New(err1.Error() + err2.Error())
18
David Budworth

@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 で入手できます。

7
Ben Campbell

https://github.com/hashicorp/go-multierror に興味があるかもしれません。これは、「エラーのリストを単一のエラーとして表すためのGo(golang)パッケージ」と記述されています。

3
Mark Lawrence

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)

errors.Unwrapのプレイグラウンドの例

さらに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)を指定するときにスタックトレースを出力するオプションと同様に。

彼のブログでパッケージに関する追加情報を見つけることができます: here および here

3
Feckmore

この機能を使用します。

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

0
Sean F