🤯

nilが返ってくる可能性のあるものに対してのメソッドは値レシーバorポインタレシーバどちらで実装すべきか?

2024/12/31に公開

今年この記事に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になる)

参考文献

https://tech.yappli.io/entry/methods-and-pointer-indirection-in-go

Discussion