レシーバには 値レシーバ と ポインタレシーバ を指定する事が出来ます。
値レシーバの指定
レシーバの値を変更しない場合、基本的に値レシーバを使用します。
package main
import (
"fmt"
)
// 構造体定義
type myStruct struct {
name string
}
// メソット定義
func (m myStruct) introduction() string {
return fmt.Sprintf("名前は %s です。", m.name)
}
func main() {
m := myStruct{}
m.name = "sample_name"
fmt.Println(m.introduction()) // 名前は sample_name です。 が表示される。
}
ポインタレシーバの指定
レシーバにポインタ型を指定するケースは以下の2点になります。
- メソッドがレシーバの値を変更する場合はポインタレシーバを指定する。
- レシーバの値がnilでもメソッドを実行したい場合はポインタレシーバを指定する。
レシーバの値変更
値レシーバの指定
ポインタレシーバを指定しない場合、どのようになるかを確認します。
package main
import (
"fmt"
)
// 構造体定義
type myStruct struct {
name string
}
// メソット定義
func (m myStruct) setName(name string) {
m.name = name
}
func (m myStruct) getName() string {
return m.name
}
func main() {
var m myStruct
m.setName("sample_name")
fmt.Println("名前は " + m.getName() + " です") // 名前は です。 が表示される。
}
うまく名前が表示されませんでした。
ポインタレシーバの指定
レシーバをポインタ型にすると名前が表示されます。なお、レシーバがポインタ型でも構造体をポインタ指定しなくても実行出来ます。Goがポインタ型へ自動で変換し実行してくれるようです。
package main
import (
"fmt"
)
// 構造体定義
type myStruct struct {
name string
}
// メソット定義
func (m *myStruct) setName(name string) {
m.name = name
}
func (m *myStruct) getName() string {
return m.name
}
func main() {
var m myStruct
m.setName("sample_name")
fmt.Println("名前は " + m.getName() + " です") // 名前は sample_name です。 が表示される。
(&m).setName("test_name")
fmt.Println("名前は " + (&m).getName() + " です") // 名前は test_name です。 が表示される。
}
レシーバの値がnil
レシーバの値がnilでもメソッドを呼び出す場合については以下を参照して下さい。
その他
メソッドにポインタレシーバを指定する場合、他のメソッドもポインタレシーバにする事が恒例のようです。
例ではゲッター、セッターメソッドが存在しますが、Goではゲッター、セッターメソッドは使用せず、フィールドには直接アクセスすることが推奨されているようです。ただし、複数のフィールドの値を更新したい場合はメソッドを使用しても良いようです。