借阅系统
本课属于 Coddy GO 学习旅程的“面向对象编程”单元。第 100 课,共 107 课。
挑战
简单让我们为图书管理项目构建借阅系统吧!你将创建一个 Library 结构体,用于管理图书和用户集合,并通过方法处理借出和归还操作,同时进行适当的验证。
你需要将代码组织到四个文件中:
book.go:使用上一课中的Book结构体,其中包含ID、Title、Author、ISBN和Available字段。添加NewBook构造函数,将新图书初始化为可借阅状态。user.go:使用包含ID、Name、Email和BorrowedBooks(图书 ID 的切片)的User结构体。添加NewUser构造函数,将新用户的已借图书列表初始化为空。library.go:创建一个Library结构体,使用映射存储图书和用户(以各自的 ID 为键)。构建以下组件:- 创建
NewLibrary构造函数,将图书和用户的映射初始化为空 - 创建
AddBook方法,将图书添加到图书馆 - 创建
AddUser方法,将用户添加到图书馆 - 创建
Borrow方法,接收用户 ID 和图书 ID,验证操作,将图书标记为不可借阅,将图书 ID 添加到用户的已借图书列表中,并在发生问题时返回错误 - 创建
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 在线编译器