nakaoka3の技術ブログ

2023年中に52本なにか書きます

Goのブランク演算子 blank identifier (`_`)

ペアプロをしていて、雑談的に「そういえばGoのアンダースコア(_)の変数って、慣習的に _にしてるだけなんでしたっけ、特別なものなんでしたっけ」ということを話しました。結論から言うとGoの _ はblank identifier (ブランク識別子) というもので、普通の変数とは違うものでした。

Effective Go のページにわかりやすい説明がありました。「ブランク識別子には、任意の型の任意の値を代入または宣言できますが、その値は無害に破棄されます。これは、Unix の /dev/null ファイルへの書き込みに少し似ています。」とのことです。

The blank identifier can be assigned or declared with any value of any type, with the value discarded harmlessly. It's a bit like writing to the Unix /dev/null file:

go.dev

なので _ は普通の変数のようには使えません。以下のコードは何も代入できてないので、no new variables on left side of :=というビルドエラーが発生します。

// ビルドできない
_ := "hello"

以下のように3つ組みを返す関数で、普通の変数だと1つの変数に2つの戻り値に代入することはできませんが、_ は2つの戻り値を捨てることができます。

// ビルドできる
func main() {
    a, _, _ := triple("Hello")
    fmt.Println(a)
}

func triple(s string) (string, string, string) {
    return s, s, s
}

当然ですが、_ は何も持ってないので以下のように _ を参照するとcannot use _ as value or typeというビルドエラーが発生します。

// ビルドできない
func main() {
    a, _, _ := triple("Hello")
    fmt.Println(a)
    fmt.Print(_)
}