ハマりましたwwww
func main() { var e1 error e1 = x() if e1 == nil { fmt.Printf("e1 == nil: %v\n", e1) } else { fmt.Printf("e1 != nil: %v\n", e1) } var e2 *NyanError e2 = x() if e2 == nil { fmt.Printf("e2 == nil: %v\n", e2) } else { fmt.Printf("e2 != nil: %v\n", e2) } } func x() *NyanError { return nil } // エラー type NyanError struct { } func (e *NyanError) Error() string { return "にゃー" }
出力
e1 != nil: にゃー e2 == nil: にゃー
どゆこと?
https://play.golang.org/p/z5pdAdI0YZ
正直go書き始めて3日程度の俺にはよくわからんのだが、errorのようなinterface型の変数は、実行時にnilが渡されたとしても渡されるであろう構造体の型情報を保持しているらしい。んで、この型情報も一致しないと == nil
にならないらしいマジすか。nilリテラルは値がnilで型もnilだが、e1は値がnilで型がNyanError、なので不一致。
値はnilなのに、 fmt.Printf(“%v”, e1) で “にゃー” とか表示されるのは変数が型情報を持っているからなんすね…
interface型変数の場合 e == nil || reflect.ValueOf(e).IsNil()
と判定するといいらしい。これは、変数の型情報を無くして値だけで比較する方法って事ですか。
しかし、変数の型が構造体型かinterface型かで動き変わるなんて思わんかったよw