Goのnilだけどnilじゃないちょっとだけnilな値

## 突然ですが、以下のコードが何を意味しているかわかりますか？

```go
var _ I = (*T)(nil)
```



### 答え

型チェックです。

次のようなコードが存在するとして、TがインターフェイスIを満たすことを宣言しています。

```go
type I interface {}
type T struct {}
```

このチェックが行われるのは実行時ではなくコンパイル時です。また、割り当て先がブランク識別子`_`であるため、バイトコードにはこのコードに対応する部分は出力されません。

[Effective Go \- The Go Programming Language](https://golang.org/doc/effective_go.html#blank_implements)

### それはわかったけど、`(*T)(nil)`ってキモくない？ というか何してるの？

型の変換です。普通であれば`float32(1)`のように書けますが、前に`*`がつく場合はカッコで囲む必要があります。`*`はポインタを現すために使うので、その場合と区別するために必要だとか。

[Go's Declaration Syntax \- The Go Blog](https://blog.golang.org/gos-declaration-syntax)

つまり、次の2つのコードは同じことをしています。

```go
var a = (*T)(nil)
```

```go
var b *T
```

後者を使用して冒頭のコードを書き換えるなら次のようになります。

```go
var b *T
var _ I = b
```

ここで、`a`は`nil`から生成され、`b`はデフォルト値で初期化されていますので、両者共に直感的には`nil`だと思われるのですが、実はこれらは同時に**インターフェイス値**でもあります。



## nilが型を持っている？

次のコードと実行結果を眺めてみてください。

```go
package main

import (
	"fmt"
)

type T struct {}

func main() {
    var b *T
    fmt.Println(b == nil) 
}
```

```
true
```

`b`は`nil`なので当然の結果ですね。

次に`reflect`を使って型を調べてみます。

```go
package main

import (
	"fmt"
	"reflect"
)

type T struct {}

func main() {
    var b *T
    fmt.Println(reflect.TypeOf(b))
}
```

```
*main.T
```

どうやら`b`は**型**と**値**を持っているようです。

こうなると、`b`はただの`nil`ではなく**インターフェイス値**であると考えるのが自然ですね。

## インターフェイス値は動的な型と値を持つ

簡単な例として、空のインターフェイス`I`を定義して、インターフェイス値`i`に`T`のインスタンスへのポインタを代入してみます。

```go
package main

import (
	"fmt"
	"reflect"
)

type I interface {}
type T struct {}

func main() {
    var i I
    fmt.Println(i == nil)
    fmt.Println(reflect.TypeOf(i))

    i = &T{}
    fmt.Println(i == nil)
    fmt.Println(reflect.TypeOf(i))

    i = nil
    fmt.Println(i == nil)
    fmt.Println(reflect.TypeOf(i))
}
```

```
true
<nil>
false
*main.T
true
<nil>
```

インターフェイス値`i`の型と値は変化し、最後は再び`nil`を代入され、元の状態に戻りました。

## インターフェイス値は別の型に変換できる

代入ではなく、明示的な変換を行ってみます。

`U`という構造体を追加しました。

```go
package main

import (
	"fmt"
	"reflect"
)

type T struct {}
type U struct {}

func main() {
    var b *T
    var c = (*U)(b)
    fmt.Println(c == nil) 
    fmt.Println(reflect.TypeOf(c))
}
```

```
true
*main.U
```

`b`を`U`に変換したものは依然として`nil`を値として持ちますが、型は`U`になります。

##  ただし、`interface{}`への変換を除く

では次に`b`を`interface{}`に変換してみます。

```go
package main

import (
	"fmt"
)

type T struct {}

func main() {
    var b *T
    var d = interface{}(b)
    fmt.Println(d == nil)
    fmt.Println(reflect.TypeOf(d))
}
```

```
false
*main.T
```

おや…？ もう少し検証してみましょう。再び構造体`U`と`b`を`U`に変換した`c`を追加します。
そして`b`と`c`をそれぞれ`interface{}`に変換してみます。

```go
package main

import (
	"fmt"
	"reflect"
)

type T struct {}
type U struct {}

func main() {
    var b *T
    var c = (*U)(b)
    var d = interface{}(b)
    var e = interface{}(c)
    fmt.Println(reflect.TypeOf(b))
    fmt.Println(reflect.TypeOf(c))
    fmt.Println(reflect.TypeOf(d))
    fmt.Println(reflect.TypeOf(e))
}
```

```
*main.T
*main.U
*main.T
*main.U
```

`T`そして`U`を`interface{}`に変換した場合、型が変化していないことに注目してください。

これが、先ほど`nil`との比較が`false`になった原因です。

## まとめ

- Goには**インターフェイス値**というものがあり、**型**と**値**を持っている。
- **インターフェイス値**の**型**と**値**はそれぞれ動的である。

- `nil`以外のものから`interface{}`に変換された**インターフェイス値**は、**値**としては`nil`を持っていたとしても、依然として`nil`以外の**型**を持つため、`nil`との比較が`false`になる。


もしこの記事に興味を持っていただけたなら、[Go Data Structures: Interfaces](https://research.swtch.com/interfaces) あるいは「プログラミング言語 Go 7章 インターフェイス」に「インターフェイス値」「インターフェイスの動的な型」「インターフェイスの動的な値」「型記述子」などの情報がまとまっています。