管理者用CLIインターフェース
CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 103/107。
チャレンジ
簡単Command Patternを使って、Library Management Systemのコマンドラインインターフェースを構築しましょう! 本演習では、書籍の追加、ユーザーの登録、貸出操作の管理といった管理者コマンドを処理するCLIを、すっきりと拡張しやすいアーキテクチャで作成します。
コードは6つのファイルに分けて整理します。
book.go:ID、Title、Author、ISBN、AvailableのJSONタグを持つBook構造体です。NewBookコンストラクターも含めます。user.go:ID、Name、Email、BorrowedBooksのJSONタグを持つUser構造体です。NewUserコンストラクターも含めます。library.go: 書籍とユーザーのマップを持つLibrary構造体です。前のレッスンで実装したAddBook、AddUser、Borrow、Returnメソッドも含めます。commands.go: ここでCommand Patternを実際に実装します!*Libraryと[]stringのargsを受け取り、文字列の結果を返すExecuteメソッドを持つCommandインターフェースを定義します。次に、以下のコマンド構造体を実装します。AddBookCommand: 4つのargs(id、title、author、isbn)を受け取ります。書籍を追加し、Book added: [title]を返します。AddUserCommand: 3つのargs(id、name、email)を受け取ります。ユーザーを追加し、User added: [name]を返します。BorrowCommand: 2つのargs(userID、bookID)を受け取ります。成功時はBorrowed: [bookID]を、失敗時はError: [message]を返します。ReturnCommand: 2つのargs(userID、bookID)を受け取ります。成功時はReturned: [bookID]を、失敗時はError: [message]を返します。ListBooksCommand: argsは受け取りません。各書籍のIDとタイトルを、[id]: [title]形式で1行ずつ返します。空の場合はNo booksを返します(書籍はID順に並べます)。
コマンドに必要な数の引数が渡されなかった場合は、
Error: insufficient argumentsを返します。cli.go:Libraryへのポインターと、コマンド名からCommand実装へのマップを保持するCLI構造体を作成します。以下を実装します。- ライブラリでCLIを初期化し、すべてのコマンド(
addbook、adduser、borrow、return、listbooks)を登録するNewCLIコンストラクター - 入力文字列を受け取り、
strings.Fieldsを使って解析し、コマンドを検索して実行するRunメソッド。入力が空の場合はNo command providedを、認識できないコマンドの場合はUnknown command: [name]を返します。
- ライブラリでCLIを初期化し、すべてのコマンド(
main.go: ライブラリとCLIを作成し、入力からコマンドを処理します。コマンド数を読み取った後、各コマンド文字列を別々の行から読み取ります。各コマンドについてRunを呼び出し、結果を出力します。
次の入力が与えられます。
- コマンド数
- それぞれ独立した行に記述された完全なコマンド
例えば、次の入力が与えられた場合:
6
addbook B001 Go-Programming Alan-Donovan 978-0134190440
addbook B002 Clean-Code Robert-Martin 978-0132350884
adduser U001 Alice alice@test.com
borrow U001 B001
listbooks
borrow U001 B001出力は次のようになります。
Book added: Go-Programming
Book added: Clean-Code
User added: Alice
Borrowed: B001
B001: Go-Programming
B002: Clean-Code
Error: book not availableまた、次の入力が与えられた場合:
4
listbooks
addbook B100 Design-Patterns Gang-of-Four 978-0201633610
listbooks
invalidcmd test出力は次のようになります。
No books
Book added: Design-Patterns
B100: Design-Patterns
Unknown command: invalidcmdさらに、次の入力が与えられた場合:
5
adduser U001 Bob bob@email.com
borrow U001 B001
addbook B001 Golang-Guide John-Smith 123-456
borrow U001 B001
return U001 B001出力は次のようになります。
User added: Bob
Error: book not found
Book added: Golang-Guide
Borrowed: B001
Returned: B001CLIは各操作の詳細を知る必要がないことに注目してください。CLIはコマンドを検索し、実行を委譲するだけです。そのため、新しいコマンドの追加は、Commandインターフェースを実装する新しい構造体を作成し、それをCLIに登録するだけで簡単に行えます。
自分で試してみよう
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
// コマンドの数を読み取る
var n int
fmt.Scanln(&n)
// 行全体を読み取るスキャナーを作成する
scanner := bufio.NewScanner(os.Stdin)
// TODO: 新しい Library を作成する
// TODO: ライブラリを使って新しい CLI を作成する
// TODO: 各コマンドを処理する
// n 個の各コマンドについて:
// - scanner.Scan() と scanner.Text() を使ってコマンド行を読み取る
// - CLI を通じてコマンドを実行する
// - 結果を出力する
_ = scanner // scanner を使用したらこの行を削除する
}
オブジェクト指向プログラミングのすべてのレッスン
1Go オブジェクト指向の基礎
外部ファイルGo ワークスペースとモジュールパッケージとインポート公開された名前と非公開の名前Go におけるオブジェクト指向入門クラスとしての構造体構造体へのメソッド定義ポインタレシーバと値レシーバ構造体の初期化コンストラクタ関数まとめ:簡易計算機8エラー処理とOOP
error インターフェースカスタムエラー型エラーラッピング (fmt.Errorf)センチネルエラーerrors.Is() と errors.As()Panic、Defer、Recover復習 - ファイルパーサー自分で練習してみよう: Goオンラインコンパイラ