Menu
Coddy logo textTech

대출 시스템

Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 107개 중 100번째.

challenge icon

챌린지

쉬움

Library Management 프로젝트를 위한 대출 시스템을 만들어 봅시다! 도서와 사용자의 collections를 관리하고 대출 및 반납 작업을 처리하는 메서드를 갖춘 Library struct를 만들며, 적절한 유효성 검사도 포함합니다.

코드를 네 개의 파일로 구성합니다:

  • book.go: 이전 lesson에서 만든 Book struct에 ID, Title, Author, ISBN, Available 필드를 포함합니다. books를 available 상태로 초기화하는 NewBook constructor도 포함합니다.
  • user.go: ID, Name, Email, BorrowedBooks(book IDs의 slice)를 포함하는 User struct입니다. users를 empty borrowed list로 초기화하는 NewUser constructor도 포함합니다.
  • library.go: books와 users를 maps(각각의 IDs를 키로 사용)에 저장하는 Library struct를 만듭니다. 다음 components를 구현합니다:
    • books와 users를 위한 empty maps를 초기화하는 NewLibrary constructor
    • library에 book을 추가하는 AddBook method
    • library에 user를 추가하는 AddUser method
    • user ID와 book ID를 받고, 작업을 검증하고, book을 unavailable로 표시하고, book ID를 user's borrowed list에 추가하며, 문제가 발생하면 error를 반환하는 Borrow method
    • 대출 과정을 되돌리는 Return method: book을 available로 표시하고 user's borrowed list에서 제거합니다

    Borrow method는 다음 errors를 반환해야 합니다:

    • user ID가 존재하지 않으면 user not found
    • book ID가 존재하지 않으면 book not found
    • book이 이미 대출된 상태이면 book not available

    Return method는 다음 errors를 반환해야 합니다:

    • user ID가 존재하지 않으면 user not found
    • book ID가 존재하지 않으면 book not found
    • book이 이미 available 상태이면 book not borrowed
  • main.go: library를 만들고, books와 users를 추가한 다음, 대출/반납 작업을 처리하여 모든 것을 하나로 연결합니다.

    books의 수를 읽은 다음, 각 book에 대해 ID, title, author, ISBN을 읽습니다. 그런 다음 users의 수를 읽고, 각 user에 대해 ID, name, email을 읽습니다. 이후 operations의 수를 읽으며, 각 operation은 borrow [userID] [bookID] 또는 return [userID] [bookID] 중 하나입니다.

    각 operation에 대해 성공하면 OK를 출력하고, 실패하면 Error: [message]를 출력합니다.

다음 inputs가 제공됩니다:

  • books의 수, 이어서 각 book의 ID, title, author, ISBN(각각 별도의 line)
  • users의 수, 이어서 각 user의 ID, name, email(각각 별도의 line)
  • operations의 수, 이어서 각 operation을 별도의 line에 입력

예를 들어 다음이 주어졌다고 합시다:

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가 central coordinator로 작동하는 방식에 주목하세요. state를 수정하기 전에 모든 operation을 검증하여 books와 users가 동기화된 상태를 유지하도록 합니다. pointer receivers를 사용하면 methods가 maps에 저장된 실제 data를 수정할 수 있습니다!

직접 해보기

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 컴파일러