問7 Itemに魂を込めよ
中段 / 目安 30分
「いよいよ本丸、Item 型の移植です」
凛さんの声が少しだけ弾みました。「構造体、税込価格メソッド、売切れ化メソッド、そして不正な商品を生まれさせない NewItem 関数。TypeScript道場の問4、覚えていますか。あれの Go 版です」
構造体は、値をひとまとめにした型です。別の題材として、読書記録を考えます。
Go
type Reading struct {
Title string
Pages int
Done bool
}メソッドは、関数名の前にレシーバを付けて書きます。値レシーバは写しを受け取るので、読むだけの処理に使います。元の記録を変えるには、*Reading というポインタレシーバを使います。
Go
func (r Reading) PageCount() int {
return r.Pages
}
func (r *Reading) Finish() {
r.Done = true
}フィールドは r.Pages のようにドットで読み、r.Done = true のように代入します。税込計算では整数同士の割り算を使います。たとえば時間を分に換算する 125 / 60 の結果は 2 で、端数は切り捨てられます。
Go のコンストラクタは特別な構文ではなく、検証して構造体を作る普通の関数です。
Go
func NewReading(title string) (*Reading, error) {
if title == "" {
return nil, errors.New("書名が必要です")
}
return &Reading{Title: title}, nil
}Reading{Title: title} はフィールド名を指定して値を作る書き方です。省略したフィールドにはゼロ値が入ります。先頭の & はその値のポインタを返し、失敗時は値の代わりに nil を返します。2つ目の戻り値は失敗なら errors.New(...)、成功なら nil です。
エラーの理由を文字列として読むときは err.Error() を使います。たとえば次のコードでは message が 書名が必要です になります。
Go
err := errors.New("書名が必要です")
message := err.Error()作れなかったときに error を返すのが要点です。不正な値を持つ Item を、そもそも存在させない。 検証を入口の1か所に集めておけば、その先では中身を疑わずに済みます。型の門番を、Go 側にも立てます。
完成条件
次の4つを確認し、ひな形の未完成部分を埋めてください。構造体、検証の if の枠、呼び出しと表示は完成済みです。
Item構造体 —Name(string)Price(int)Sold(bool)TaxIncluded()— 税込価格を返す。消費税は10%で、端数は切り捨てMarkSold()—Soldをtrueにする。元の Item が変わることNewItem(name, price)— 検証つきで(*Item, error)を返す
検証は、名前が空なら 商品名は必須です、価格が 0 以下なら 価格は1円以上です です。両方不正なら名前を先に調べます。
動作を確かめる runItem 関数は用意済みです。名前と価格を受け取り、NewItem で作って売切れ化し、結果を返します。作れなかったときは エラー: に続けて理由を返してください。
要件
- 用意された
Item構造体とrunItemを使う。表示やメソッド呼び出しは書き直さない TaxIncluded()の値レシーバはそのまま使い、10%税込・端数切り捨ての計算を返す。MarkSold()は元のItemを変えられるレシーバに直し、SoldをtrueにするNewItemの用意された検証枠では、失敗時にnilと指定のエラー、成功時にNameとPriceを入れたItemのポインタとnilを返す。名前の検証を先にする
ヒント
前のヒントを開くと次が開きます。開かずに解けると未開封クリアです