エラーの内容
./main.go:12:15: multiple-value in single-value context
ビルドがこのエラーで失敗しました。Goコンパイラは、複数の値を返す関数が1つの値しか期待されない箇所で使われていることを伝えています。Goはこの点に厳格で、PythonやJavaScriptのように戻り値を暗黙に無視することはできません。
なぜ発生するのか
失敗する可能性のあるGoの関数のほとんどは (value, error) を返します。Goのコンパイラは戻り値のスキップを許可しません。そのような関数の出力を式に直接渡したり、関数の引数として使ったり、1つの値しか入らない箇所に代入しようとした瞬間に、このエラーが発生します。
よくあるシナリオ1:代入の不一致
// 誤り — os.Open は (*File, error) を返す
f := os.Open("config.json")
// 正しい
f, err := os.Open("config.json")
if err != nil {
log.Fatal(err)
}
よくあるシナリオ2:複数の戻り値を持つ関数を別の関数に直接渡す
// 誤り — strconv.Atoi は (int, error) を返す
fmt.Println(strconv.Atoi("42"))
// 正しい
n, err := strconv.Atoi("42")
if err != nil {
log.Fatal(err)
}
fmt.Println(n)
よくあるシナリオ3:式の中で複数の戻り値を使う
// 誤り
total := getValue() + 10
// getValue() がこのように定義されている場合:
func getValue() (int, error) {
return 42, nil
}
// 正しい
val, err := getValue()
if err != nil {
log.Fatal(err)
}
total := val + 10
よくあるシナリオ4:ネストされた関数呼び出し
// 誤り — json.Marshal は ([]byte, error) を返す
os.Stdout.Write(json.Marshal(data))
// 正しい
b, err := json.Marshal(data)
if err != nil {
log.Fatal(err)
}
os.Stdout.Write(b)
ステップごとの修正方法
ステップ1:エラーの原因となっている行を見つける
コンパイラは正確なファイルと行番号を教えてくれます:
./main.go:12:15: multiple-value in single-value context
12行目、15列目に移動し、右辺にある関数呼び出しを探してください。
ステップ2:関数のシグネチャを確認する
エディタで関数にカーソルを合わせるか、ドキュメントを確認してください:
// 関数の戻り値を確認する
go doc os.Open
// 出力:func Open(name string) (*File, error)
ステップ3:すべての戻り値を受け取る
すべての戻り値には変数が必要です — 使う予定がない値も含めて:
// 不要な値を破棄するにはブランク識別子 _ を使う
f, _ := os.Open("config.json")
とはいえ、プロダクションコードでエラーを破棄するのは通常良くありません。ブランク識別子は簡単なスクリプトや、エラーが絶対に発生しないと確信できる場合には問題ありません。
ステップ4:コードを再構成する
複数の戻り値を持つ関数呼び出しが式の中に埋め込まれている場合、まず取り出してください:
// 修正前(壊れている)
result := process(strconv.Atoi(input))
// 修正後(直った)
n, err := strconv.Atoi(input)
if err != nil {
return fmt.Errorf("無効な入力: %w", err)
}
result := process(n)
特殊ケース:エラー以外の複数の値を返す関数
複数の値を返す関数がすべてエラーを含むわけではありません。次のようなケースもあります:
func minMax(nums []int) (int, int) {
// ...
return min, max
}
// 誤り
fmt.Println("最小値:", minMax(nums))
// 正しい
min, max := minMax(nums)
fmt.Println("最小値:", min, "最大値:", max)
Goでは、受け取る関数のパラメータリストが完全に一致する場合に限り、複数の戻り値を持つ関数を別の関数に直接渡すことができます。これは稀なケースであり、可読性のために一般的には避けられています — 明示的な変数名を使うとコードがずっと読みやすくなります。
修正の確認
go build ./...
ビルドが成功した場合、何も出力されません。次のコマンドも実行できます:
go vet ./...
リリース前に、その他の型関連の問題を検出するために使えます。
今後このエラーを避けるためのヒント
- Go対応のIDEを使う — GoLandやVS CodeのGo拡張機能は、ファイルを保存する前にこのエラーを検出してくれます。
- CIパイプラインで
golangci-lintを有効にする — このエラーをはじめ、数十の類似した問題を自動的に検出します。 - 複数の戻り値を持つ関数を連鎖させない — たとえ1行増えても、常に名前付き変数に先に代入してください。深夜2時にデバッグしている将来の自分が感謝するでしょう。
- ブランク識別子は最終手段 —
_でエラーを破棄する場合は、なぜ無視しても安全なのかを説明するコメントを追加してください。

