Menu
CoddyTech

Hệ thống mượn sách

Thuộc phần Lập trình hướng đối tượng trong hành trình GO của Coddy. Bài học 100 trên 107.

challenge icon

Thử thách

Dễ

Hãy xây dựng hệ thống mượn sách cho dự án quản lý thư viện của chúng ta! Bạn sẽ tạo một struct Library để quản lý các bộ sưu tập sách và người dùng, với các phương thức xử lý việc mượn và trả sách, đồng thời kiểm tra tính hợp lệ.

Bạn sẽ sắp xếp code trong bốn tệp:

  • book.go: struct Book từ bài học trước, gồm các trường ID, Title, Author, ISBN và Available. Thêm hàm khởi tạo NewBook để khởi tạo sách ở trạng thái có sẵn.
  • user.go: struct User gồm ID, Name, Email và BorrowedBooks (slice chứa ID sách). Thêm hàm khởi tạo NewUser để khởi tạo người dùng với danh sách mượn trống.
  • library.go: Tạo struct Library để lưu sách và người dùng trong các map (được lập chỉ mục bằng ID của chúng). Xây dựng các thành phần sau:
    • Hàm khởi tạo NewLibrary tạo các map trống cho sách và người dùng
    • Phương thức AddBook thêm sách vào thư viện
    • Phương thức AddUser thêm người dùng vào thư viện
    • Phương thức Borrow nhận ID người dùng và ID sách, kiểm tra tính hợp lệ của thao tác, đánh dấu sách là không có sẵn, thêm ID sách vào danh sách sách đã mượn của người dùng và trả về lỗi nếu có sự cố
    • Phương thức Return đảo ngược quy trình mượn: đánh dấu sách là có sẵn và xóa sách khỏi danh sách đã mượn của người dùng

    Phương thức Borrow cần trả về các lỗi sau:

    • user not found nếu ID người dùng không tồn tại
    • book not found nếu ID sách không tồn tại
    • book not available nếu sách đã được mượn

    Phương thức Return cần trả về các lỗi sau:

    • user not found nếu ID người dùng không tồn tại
    • book not found nếu ID sách không tồn tại
    • book not borrowed nếu sách đã có sẵn
  • main.go: Kết hợp mọi thứ bằng cách tạo thư viện, thêm sách và người dùng, sau đó xử lý các thao tác mượn và trả sách.

    Đọc số lượng sách, sau đó đọc ID, tiêu đề, tác giả và ISBN của từng sách. Tiếp theo, đọc số lượng người dùng, rồi đọc ID, tên và email của từng người dùng. Sau đó, đọc số lượng thao tác, mỗi thao tác là borrow [userID] [bookID] hoặc return [userID] [bookID].

    Với mỗi thao tác, in ra OK nếu thành công hoặc Error: [message] nếu thất bại.

Đầu vào sẽ gồm:

  • Số lượng sách, sau đó là ID, tiêu đề, tác giả và ISBN của từng sách (mỗi thông tin trên một dòng riêng)
  • Số lượng người dùng, sau đó là ID, tên và email của từng người dùng (mỗi thông tin trên một dòng riêng)
  • Số lượng thao tác, sau đó là từng thao tác trên một dòng riêng

Ví dụ, với đầu vào:

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

Đầu ra của bạn sẽ là:

OK
Error: book not available
OK
Error: user not found

Và với đầu vào:

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

Đầu ra của bạn sẽ là:

OK
Error: book not available
OK

Và với đầu vào:

1
B001
Go in Action
William Kennedy
978-1617291784
1
U001
Dave Miller
dave@test.com
2
return U001 B001
borrow U001 B999

Đầu ra của bạn sẽ là:

Error: book not borrowed
Error: book not found

Lưu ý Library đóng vai trò điều phối trung tâm. Thư viện kiểm tra tính hợp lệ của mọi thao tác trước khi thay đổi trạng thái, đảm bảo sách và người dùng luôn đồng bộ. Dùng các phương thức nhận con trỏ để phương thức có thể sửa đổi dữ liệu thực tế được lưu trong các map!

Tự làm thử

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Đọc số lượng sách
	var numBooks int
	fmt.Fscanln(reader, &numBooks)

	// TODO: Tạo thư viện mới

	// TODO: Đọc thông tin từng cuốn sách (ID, Title, Author, ISBN trên các dòng riêng)
	// và thêm chúng vào thư viện
	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: Tạo sách và thêm vào thư viện
	}

	// Đọc số lượng người dùng
	var numUsers int
	fmt.Fscanln(reader, &numUsers)

	// TODO: Đọc thông tin từng người dùng (ID, Name, Email trên các dòng riêng)
	// và thêm chúng vào thư viện
	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: Tạo người dùng và thêm vào thư viện
	}

	// Đọc số lượng thao tác
	var numOps int
	fmt.Fscanln(reader, &numOps)

	// TODO: Xử lý từng thao tác
	// Định dạng: "borrow [userID] [bookID]" hoặc "return [userID] [bookID]"
	for i := 0; i < numOps; i++ {
		line, _ := reader.ReadString('\n')
		line = strings.TrimSpace(line)
		parts := strings.Split(line, " ")

		// TODO: Phân tích thao tác và gọi phương thức phù hợp
		// In ra "OK" nếu thành công hoặc "Error: [message]" nếu thất bại
	}
}

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Go online