ペアプロをしていて、雑談的に「そういえば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:
なので _
は普通の変数のようには使えません。以下のコードは何も代入できてないので、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(_) }