🤯
nilが返ってくる可能性のあるものに対してのメソッドは値レシーバorポインタレシーバどちらで実装すべきか?
今年この記事に3回ガッツリお世話になったのでもう神棚に祀りたいです。
結論
ポインタレシーバ
理由は下記のコード参照
panicになるコード
package main
import (
"fmt"
)
type user struct {}
// 値レシーバにする
func (u user) something() bool {
return false
}
func main() {
var u *user
fmt.Printf("bool: %v\n", u.something())
}
panicにならないコード
package main
import (
"fmt"
)
type user struct {}
// ポインタレシーバにする
func (u *user) something() bool {
return false
}
func main() {
var u *user
fmt.Printf("bool: %v\n", u.something())
}
見解
ポインタ型変数の値レシーバメソッド呼び出しは自動解決するので、メソッド実行時に、ポインタ型をデリファレンスして値に直したあとに実行する
なので、nilのポインタ型に対してデリファレンスすることになり、nilぽエラーでpanicになる
逆に、ポインタ型変数で、ポインタレシーバメソッド呼び出しだと、ポインタに対して実装したメソッドなので、メソッドの実行自体は可能(そのあとレシーバ変数のフィールドにアクセスしようとするとpanicになる)
参考文献
Discussion