こちらは Goクイズ Advent Calendar 2020 - Qiita の3日目の記事です。
問題
序盤と言うこともあるのでシンプルな一問です。
package main import "fmt" func main() { var x = nil fmt.Println(x) }
結果はどちらでしょう?
- compile error
<nil>
解答
https://play.golang.org/p/lG_k0E0oiDz
解説
スクロールした先にあります!
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
正解は、1の compile error
です。
このコードを実行すると、 ./prog.go:6:6: use of untyped nil
と表示されビルドに失敗します。
何故型のないnilは使えないのか?
今回、var x = nil
と言う表現がありました。
これは、変数宣言の文で、型が省略されています。全ての変数は静的型を持つので、ここで何かしらの型を推論する必要があります。
しかし、ここで初期化用に与えられている nil
は、型の付いていない値で、デフォルトの型も存在しません。
そのため、変数に対して割り当てる型を推論することが出来ずエラーになります(と言う理解です)
GoのSpec上でも、このような変数宣言はillegalだとして明記されています。
The predeclared value nil cannot be used to initialize a variable with no explicit type.
https://golang.org/ref/spec#Variable_declarations
補足1: 変数の動的型と静的型について
Goの変数は、静的型 (static type) と、動的型 (dynamic type) の2つを持ちます。
静的型は、その変数に割り当てられた型で、動的型は、インタフェース型の変数に格納された値の型を表します。 全ての変数は静的型を持っています。int, boolなどの型や、io.Writerなどのインタフェース型など、その変数に対してどのような操作が可能か紐付ける情報として必ず存在しています。
一方で、動的型はその限りではありません。静的型がインタフェース型である変数に、事前に定義された識別子 nil
で特定される値を代入した場合、この変数の動的型は 型なし
となります。
補足2: 型なしの定数について
nil以外の型の無い値としては、定数リテラルが挙げられます。
const ( i = 123 s = "abc" )
と言った形で定数を宣言した時、これらの値は型無しの定数となります。
ただし、これらの値を変数に代入しようとした時、変数としてどの型に割り当てられるかが決まっているため問題となりません。
An untyped constant has a default type which is the type to which the constant is implicitly converted in contexts where a typed value is required...