貸出システム
CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 100/107。
チャレンジ
簡単Library Management プロジェクトの貸出システムを構築しましょう!書籍とユーザーのコレクションを管理する Library struct を作成し、貸出と返却の操作を処理するメソッドを実装します。もちろん、適切な検証も行います。
コードは4つのファイルに分けて整理します。
book.go:前のレッスンで作成したBookstruct を使用します。ID、Title、Author、ISBN、Availableフィールドを含めます。書籍を利用可能な状態で初期化するNewBookconstructor も含めてください。user.go:ID、Name、Email、BorrowedBooks(書籍 ID のスライス)を持つUserstruct を使用します。ユーザーを空の貸出リストで初期化するNewUserconstructor も含めてください。library.go:書籍とユーザーをマップ(それぞれの ID をキーとする)に格納するLibrarystruct を作成します。次の要素を実装してください。- 書籍とユーザー用の空のマップを初期化する
NewLibraryconstructor - 書籍をライブラリに追加する
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.Fscanln(reader, &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.Fscanln(reader, &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.Fscanln(reader, &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復習 - ファイルパーサー自分で練習してみよう: Goオンラインコンパイラ