貸出システム
CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 100/107。
チャレンジ
簡単図書館管理プロジェクトの貸出システムを構築しましょう!本とユーザーのコレクションを管理する Library 構造体を作成し、適切なバリデーションを含む貸出および返却操作を処理するメソッドを実装します。
コードは以下の4つのファイルに分けて構成します:
book.go: 前回のレッスンで作成した、ID、Title、Author、ISBN、およびAvailableフィールドを持つBook構造体です。本を「利用可能」として初期化するNewBookコンストラクタを含めてください。user.go:ID、Name、Email、およびBorrowedBooks(本のIDのスライス)を持つUser構造体です。ユーザーを空の貸出リストで初期化するNewUserコンストラクタを含めてください。library.go: 本とユーザーを(それぞれのIDをキーとして)マップに保存するLibrary構造体を作成します。以下のコンポーネントを構築してください:- 本とユーザーのための空のマップを初期化する
NewLibraryコンストラクタ - 本を図書館に追加する
AddBookメソッド - ユーザーを図書館に追加する
AddUserメソッド - ユーザーIDと本IDを受け取り、操作を検証し、本を「利用不可」に設定し、ユーザーの貸出リストに本IDを追加する
Borrowメソッド。問題が発生した場合はエラーを返します。 - 貸出プロセスを逆に行う
Returnメソッド。本を「利用可能」に設定し、ユーザーの貸出リストから削除します。
Borrowメソッドは以下のエラーを返す必要があります:- ユーザーIDが存在しない場合は
"user not found" - 本IDが存在しない場合は
"book not found" - 本がすでに貸し出されている場合は
"book not available"
Returnメソッドは以下のエラーを返す必要があります:- ユーザーIDが存在しない場合は
"user not found" - 本IDが存在しない場合は
"book not found" - 本がすでに利用可能な状態(貸し出されていない)の場合は
"book not borrowed"
- 本とユーザーのための空のマップを初期化する
main.go: 図書館を作成し、本とユーザーを追加し、貸出/返却操作を処理することで、すべてをまとめます。本の数を読み取り、次に各本のID、タイトル、著者、ISBNを読み取ります。次にユーザーの数を読み取り、各ユーザーのID、名前、メールアドレスを読み取ります。その後、操作の数を読み取ります。各操作は
"borrow [userID] [bookID]"または"return [userID] [bookID]"の形式です。各操作について、成功した場合は
"OK"を、失敗した場合は"Error: [message]"を出力してください。
以下の入力が提供されます:
- 本の数、続いて各本のID、タイトル、著者、ISBN(それぞれ別々の行)
- ユーザーの数、続いて各ユーザーのID、名前、メールアドレス(それぞれ別々の行)
- 操作の数、続いて各操作(別々の行)
例えば、以下のように入力された場合:
2
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Clean Code
Robert Martin
978-0132350884
1
U001
Alice Smith
alice@library.com
4
borrow U001 B001
borrow U001 B001
return U001 B001
borrow U002 B001出力は以下のようになります:
OK
Error: book not available
OK
Error: user not foundまた、以下のように入力された場合:
1
B100
Design Patterns
Gang of Four
978-0201633610
2
U001
Bob Jones
bob@email.com
U002
Carol White
carol@email.com
3
borrow U001 B100
borrow U002 B100
return U001 B100出力は以下のようになります:
OK
Error: book not available
OKまた、以下のように入力された場合:
1
B001
Go in Action
William Kennedy
978-1617291784
1
U001
Dave Miller
dave@test.com
2
return U001 B001
borrow U001 B999出力は以下のようになります:
Error: book not borrowed
Error: book not foundLibraryが中央のコーディネーターとして機能し、状態を変更する前にすべての操作を検証して、本とユーザーの同期を保つ仕組みに注目してください。ポインタレシーバを使用することで、メソッドがマップに保存されている実際のデータを変更できるようになります!
自分で試してみよう
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// 本の数を読み込む
var numBooks int
fmt.Scanln(&numBooks)
// TODO: 新しいライブラリを作成する
// TODO: 各本の詳細(ID、Title、Author、ISBN を別々の行で)を読み込む
// そしてそれらをライブラリに追加する
for i := 0; i < numBooks; i++ {
id, _ := reader.ReadString('\n')
id = strings.TrimSpace(id)
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
author, _ := reader.ReadString('\n')
author = strings.TrimSpace(author)
isbn, _ := reader.ReadString('\n')
isbn = strings.TrimSpace(isbn)
// TODO: 本を作成してライブラリに追加する
}
// ユーザーの数を読み込む
var numUsers int
fmt.Scanln(&numUsers)
// TODO: 各ユーザーの詳細(ID、Name、Email を別々の行で)を読み込む
// そしてそれらをライブラリに追加する
for i := 0; i < numUsers; i++ {
id, _ := reader.ReadString('\n')
id = strings.TrimSpace(id)
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
email, _ := reader.ReadString('\n')
email = strings.TrimSpace(email)
// TODO: ユーザーを作成してライブラリに追加する
}
// 操作の数を読み込む
var numOps int
fmt.Scanln(&numOps)
// TODO: 各操作を処理する
// 形式: "borrow [userID] [bookID]" または "return [userID] [bookID]"
for i := 0; i < numOps; i++ {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
parts := strings.Split(line, " ")
// TODO: 操作を解析し、適切なメソッドを呼び出す
// 成功時には "OK" を、失敗時には "Error: [message]" を出力する
}
}
オブジェクト指向プログラミングのすべてのレッスン
1Go オブジェクト指向の基礎
外部ファイルGo ワークスペースとモジュールパッケージとインポート公開された名前と非公開の名前Go におけるオブジェクト指向入門クラスとしての構造体構造体へのメソッド定義ポインタレシーバと値レシーバ構造体の初期化コンストラクタ関数まとめ:簡易計算機8エラー処理とOOP
error インターフェースカスタムエラー型エラーラッピング (fmt.Errorf)センチネルエラーerrors.Is() と errors.As()Panic、Defer、Recover復習 - ファイルパーサー