コンテンツにスキップ

nilとは何か interfaceの構造とnil-not-equal-nilから理解する

チェック

  • [ ] 本文を確認した
  • [ ] 概要を確認した
  • [ ] タグを確認した
  • [ ] inbox/ 直下へ移行した

概要

Go の nil を言語仕様と interface 内部構造から理解する資料。 nil は keyword ではなく predeclared identifier であり、default type を持たない。 interface は型情報と値を持つため、typed nil が入ると値が nil でも interface 全体は nil ではない、という nil != nil 問題が起きる。 実務での付き合い方も扱う構成。

本文

資料の流れは次の通り。

  • nil を言語仕様から見る
  • interface の内部構造と nil != nil
  • 改善提案の歴史
  • 実務での付き合い方

nil は Go の keyword ではない。 iffuncreturngo などは keyword であり変数名に使えないが、niltruefalseiota と同じ predeclared identifier。 そのため shadowing できる。

nil := 123 // コンパイルは通る

また、predeclared identifier の中で default type を持たないのは nil だけ。 truebooliotaint として扱われるが、nil 単体では型が決まらない。

Go の interface は、内部的に型情報と値を持つ。 したがって、var p *T = nil を interface に代入すると、値 pointer は nil でも *T という型情報が入る。 この状態の interface は nil ではない。

var p *MyError = nil
var err error = p
fmt.Println(err == nil) // false

この問題は、error interface を返す関数で typed nil を返してしまうと実務上の bug になる。 interface を返す関数では、nil pointer をそのまま interface に詰めず、nil の場合は明示的に return nil する必要がある。

要点

  • nil は keyword ではなく predeclared identifier。
  • nil は default type を持たない。
  • interface は型情報と値を持つため typed nil が問題になる。
  • error を返す関数では typed nil を返さないよう注意する。
  • nil 比較は runtime 表現を理解して読む必要がある。

タグ

go #nil #interface #runtime #type-system