1. ホーム
  2. go

[解決済み] 単一値コンテキストにおける複数値

2022-08-16 21:38:39

質問

Goのエラー処理により、複数の値を持つ関数がしばしば発生します。これまでのところ、私がこれを管理する方法は非常に雑であり、よりクリーンなコードを書くためのベストプラクティスを探しています。

次のような関数があるとします。

type Item struct {
   Value int
   Name string
}

func Get(value int) (Item, error) {
  // some code

  return item, nil
}

新しい変数を item.Value に新しい変数を割り当てることができます。エラー処理を導入する前に、私の関数は単に item を返すだけであり、単純にこれを行うことができました。

val := Get(1).Value

今はこうしています。

item, _ := Get(1)
val := item.Value

最初に返された変数に直接アクセスする方法はないのでしょうか?

どのように解決するのですか?

複数値を返す関数の場合、関数を呼び出す際に結果の特定の値のフィールドやメソッドを参照することができません。

そして、もしそのうちのひとつが error であれば、そこに 理由 (これは、関数 があるかもしれない が失敗する可能性があります)、そしてあなたは ではなく をバイパスすると、その後のコードで は惨めに失敗するかもしれないからです (たとえば、実行時パニックが発生する)。

しかし、以下のような状況もあり得ます。 を知っている という状況もあるでしょう。このような場合は ヘルパー 関数 (またはメソッド) を用意すれば、その関数が error を破棄します (あるいは、まだ発生している場合はランタイムパニックを発生させます)。

コードから関数の入力値を提供し、それが動作することが分かっている場合、このようなことが起こりえます。

この素晴らしい例としては template regexp パッケージ: コンパイル時に有効なテンプレートや正規表現を提供すれば、実行時にそれらが常にエラーなくパースされることが保証されます。このような理由から template パッケージは Must(t *Template, err error) *Template 関数と regexp パッケージは MustCompile(str string) *Regexp 関数を提供します。 error を返しません。これは、入力が有効であることが保証されている場合に使用されることを意図しているからです。

例を挙げます。

// "text" is a valid template, parsing it will not fail
var t = template.Must(template.New("name").Parse("text"))

// `^[a-z]+\[[0-9]+\]$` is a valid regexp, always compiles
var validID = regexp.MustCompile(`^[a-z]+\[[0-9]+\]$`)

あなたのケースに戻る

イフ 確信が持てる Get() は生成されません。 error を生成しないように、ヘルパーの Must() を返さないヘルパー関数を作ることができます。 error を返しませんが、それでも発生した場合はランタイムパニックを発生させます。

func Must(i Item, err error) Item {
    if err != nil {
        panic(err)
    }
    return i
}

しかし、すべての場合にこれを使うのではなく、成功することが確実な場合にだけ使うようにしましょう。使い方は

val := Must(Get(1)).Value

代替・簡略化

を組み込めば、さらに簡略化することもできます。 Get() の呼び出しをヘルパー関数に組み込めば、さらに単純化できます。 MustGet :

func MustGet(value int) Item {
    i, err := Get(value)
    if err != nil {
        panic(err)
    }
    return i
}

使用方法

val := MustGet(1).Value

興味深い/関連する質問を見る。

golangで複数のリターンをパースする方法

Golangの通常の関数で'ok'のようなリターンマップを使用する。