見出し画像

Methods, Functions vs Methods, Embedded fiels for Composition and Promotion | Go日記: 『Learning Go』

Methods

package main
import (
	"fmt"
)
type Person struct {
	Name string
	Age  int
}
/*
If your method modifies the receiver, you must use a pointer receiver.
If your method needs to handle nil instances, then it must use a pointer receiver.
If your method doesn’t modify the receiver, you can use a value receiver.
Bodner, Jon. Learning Go (p.196). O'Reilly Media. Kindle 版.
*/
func (p Person) String() string {
	return fmt.Sprintf("Name is %v, %d years old.", p.Name, p.Age)
}
func (p *Person) growUp(year int) {
	if p != nil {
		p.Age += year
	}
}
func main() {
	p := Person{"John", 32}
	fmt.Println(p) // Name is John, 32 years old.
	/*
		Go automatically converts it to a pointer type.
		Bodner, Jon. Learning Go (p.197). O'Reilly Media. Kindle 版.
	*/
	p.growUp(2)
	fmt.Println(p) // Name is John, 34 years old.
}

レシーバの中身を変更するか、nil レシーバに対応する場合、ポインターレシーバを選択する必要(must)がある。

レシーバを変更しない場合、値レシーバを選択できる。

Functions vs Methods

関数とメソッド、どちらを選ぶべきか、についての指針。

The differentiator is whether or not your function depends on other data. As we’ve covered several times, package-level state should be effectively immutable. Any time your logic depends on values that are configured at startup or changed while your program is running, those values should be stored in a struct and that logic should be implemented as a method. If your logic only depends on the input parameters, then it should be a function.

Bodner, Jon. Learning Go (p.202). O'Reilly Media. Kindle 版.

ロジックに依存したひとかたまりのデータと連携して実装するならメソッド。純粋に引数にだけ依存すれば十分なロジックを実装するなら関数。

継承ではない

package main
import (
)
type Score int
type HighScore Score // This is NOT inheritance.
func main() {
	var s Score = 1
	var hs HighScore = 1
	s == hs // invalid operation: s == hs (mismatched types Score and HighScore)
}

Embedded fiels for Composition and Promotion

package main
import (
	"fmt"
)
type Human struct {
	Name string
	Age  int
}
func (h Human) SayHello() {
	fmt.Printf("Hello, my name is %v\n", h.Name)
}
type Staff struct {
	Human  // Embedded
	Skills []string
}
func (s Staff) ShowSkills() {
	fmt.Println(s.Name, s.Age, "has") // Promoted
	for _, skill := range s.Skills {
		fmt.Println(skill)
	}
}
func main() {
	john := Human{"John", 32}
	john.SayHello() // Hello, my name is John
	jonny := Staff{
		Human:  john,
		Skills: []string{"Programming", "Painting"},
	}
	jonny.ShowSkills()
	/*
		John 32 has
		Programming
		Painting
	*/
}

埋め込まれた構造体は埋め込まれたことを知らないが、埋め込まれたことによって埋め込んだほうの構造体の一部のように動作/存在する。

参考図書

SN

この記事が気に入ったらサポートをしてみませんか?