Menu
Coddy logo textTech

대출 시스템

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

challenge icon

챌린지

쉬움

도서 관리 프로젝트를 위한 대출 시스템을 구축해 봅시다! 도서와 사용자 컬렉션을 관리하는 Library 구조체를 만들고, 적절한 검증 로직을 포함하여 대출 및 반납 작업을 처리하는 메서드를 작성하게 됩니다.

코드는 다음 네 개의 파일로 구성됩니다:

  • book.go: 이전 레슨에서 만든 ID, Title, Author, ISBN, Available 필드를 가진 Book 구조체입니다. 도서를 대출 가능 상태로 초기화하는 NewBook 생성자를 포함하세요.
  • user.go: ID, Name, Email, BorrowedBooks(도서 ID 슬라이스) 필드를 가진 User 구조체입니다. 사용자를 빈 대출 목록으로 초기화하는 NewUser 생성자를 포함하세요.
  • library.go: 도서와 사용자를 맵(ID를 키로 사용)에 저장하는 Library 구조체를 만듭니다. 다음 구성 요소들을 작성하세요:
    • 도서와 사용자를 위한 빈 맵을 초기화하는 NewLibrary 생성자
    • 도서관에 도서를 추가하는 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.Scanln(&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.Scanln(&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.Scanln(&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]"를 출력
	}
}

객체 지향 프로그래밍의 모든 레슨