Menu
Coddy logo textTech

貸出システム

CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 100/107。

challenge icon

チャレンジ

簡単

Library Management プロジェクトの貸出システムを構築しましょう!書籍とユーザーのコレクションを管理する Library struct を作成し、貸出と返却の操作を処理するメソッドを実装します。もちろん、適切な検証も行います。

コードは4つのファイルに分けて整理します。

  • book.go:前のレッスンで作成した Book struct を使用します。IDTitleAuthorISBNAvailable フィールドを含めます。書籍を利用可能な状態で初期化する NewBook constructor も含めてください。
  • user.goIDNameEmailBorrowedBooks(書籍 ID のスライス)を持つ User struct を使用します。ユーザーを空の貸出リストで初期化する NewUser constructor も含めてください。
  • library.go:書籍とユーザーをマップ(それぞれの ID をキーとする)に格納する Library struct を作成します。次の要素を実装してください。
    • 書籍とユーザー用の空のマップを初期化する NewLibrary constructor
    • 書籍をライブラリに追加する 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 found

Library が中心的な調整役として機能していることに注目してください。状態を変更する前にすべての操作を検証することで、書籍とユーザーの状態が常に同期されます。ポインタレシーバーを使用すると、メソッドからマップに格納されている実際のデータを変更できます。

自分で試してみよう

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]" を出力する
	}
}

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Goオンラインコンパイラ