メソッド
型に振る舞いを付ける
Go
func (i Item) TaxIncluded() int {
return int(float64(i.Price) * 1.1)
}普通の関数との違いは、func の直後にある (i Item) だけです。これをレシーバと呼びます。「この関数は Item に属します」という宣言です。
呼び出しはドットです。
Go
item := Item{Name: "きのこ図鑑", Price: 1200}
item.TaxIncluded() // 1320関数でも書けるのに、なぜメソッドか
Go
func TaxIncluded(i Item) int // 関数
func (i Item) TaxIncluded() int // メソッド中身は同じことができます。違うのはどこに属しているかです。
メソッドにすると、Item を持っている人が item. と打った時点で、使えるものが一覧で出てきます。関数だと、名前を知らないと探せません。
もう1つ、同じ名前を別の型に付けられます。
Go
func (i Item) Label() string
func (u User) Label() string関数だと ItemLabel UserLabel のように名前で区別することになります。型に属させれば、それが要りません。
レシーバの名前は短くする
Go
func (i Item) TaxIncluded() int // よく見る形
func (item Item) TaxIncluded() int // 長いGo では、レシーバに1文字か2文字を使う習慣があります。型の頭文字を取ることが多く、Item なら i です。
同じ型のメソッドでは、レシーバ名を揃えるのも決まりです。あるメソッドで i、別で item と書くと、読む人が別物かと疑います。
レシーバもコピーされる
前のレッスンで、構造体は代入するとコピーされると書きました。メソッドのレシーバも同じです。
Go
func (i Item) MarkSoldOut() {
i.SoldOut = true // コピーを変えただけ
}
item.MarkSoldOut()
fmt.Println(item.SoldOut) // false のまま呼んでも何も起きません。エラーも出ません。静かに効かないので、最も気づきにくい詰まりどころです。
次のレッスンで、これを解決します。
要件
TaxIncludedは税込価格を返す。税率は1.1倍で小数は切り捨てLabelは商品名 税込N円の形を返すLabelの中からTaxIncludedを呼ぶ- レシーバ名は2つのメソッドで揃える
入出力例
priceLabel("きのこ図鑑", 1200) → "きのこ図鑑 税込1320円"
priceLabel("古い辞書", 999) → "古い辞書 税込1098円"
priceLabel("おまけ", 0) → "おまけ 税込0円"ヒント
編集 ゆめさく編集部