JSON 영속성 계층
Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 107개 중 102번째.
챌린지
쉬움도서 관리 시스템에 데이터 지속성을 추가해 봅시다! 도서관 데이터를 저장하기 위해 JSON 형식으로 변환하고, JSON 문자열에서 다시 데이터를 로드할 수 있는 JSON 지속성 레이어를 구현하게 됩니다. 이는 세션 간에 데이터를 보존해야 하는 모든 실제 애플리케이션에 필수적입니다.
코드는 다음 다섯 개의 파일로 구성됩니다:
book.go: 직렬화를 제어하기 위한 JSON 구조체 태그가 포함된Book구조체입니다. 각 필드는id,title,author,isbn,available에 해당하는 JSON 태그를 가져야 합니다.NewBook생성자를 포함하세요.user.go:id,name,email,borrowed_books에 대한 JSON 구조체 태그가 포함된User구조체입니다.NewUser생성자를 포함하세요.data.go: JSON 직렬화를 위한 전송 객체 역할을 하는LibraryData구조체를 생성합니다. 이 구조체는Books(Book 포인터 슬라이스)와Users(User 포인터 슬라이스)라는 두 개의 필드를 가져야 하며, 각각 적절한 JSON 태그(books및users)를 가져야 합니다.library.go: 도서와 사용자를 위한 맵을 가진Library구조체입니다. 다음 두 가지 새로운 메서드를 추가하세요:ToJSON()—json.MarshalIndent를 사용하여 2칸 들여쓰기가 적용된 형식의 JSON 문자열로 도서관 데이터를 변환합니다. 맵에 있는 모든 도서와 사용자를LibraryData구조체로 수집한 다음 직렬화해야 합니다.FromJSON(jsonStr string)— JSON 문자열을 받아LibraryData구조체로 언마샬링하고, 로드된 도서와 사용자로 도서관의 맵을 채웁니다.
main.go: 도서관을 구축하고 JSON으로 변환하여 지속성 레이어를 시연합니다.도서 수를 읽은 다음, 각 도서의 ID, 제목, 저자, ISBN을 읽습니다. 그다음 사용자 수를 읽고, 각 사용자의 ID, 이름, 이메일을 읽습니다. 도서관 데이터를 모두 채운 후,
ToJSON()을 호출하고 결과 JSON 문자열을 출력합니다.
다음 입력이 제공됩니다:
- 도서 수, 이어서 각 도서의 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출력은 다음과 같아야 합니다:
{
"books": [
{
"id": "B001",
"title": "The Go Programming Language",
"author": "Alan Donovan",
"isbn": "978-0134190440",
"available": true
},
{
"id": "B002",
"title": "Clean Code",
"author": "Robert Martin",
"isbn": "978-0132350884",
"available": true
}
],
"users": [
{
"id": "U001",
"name": "Alice Smith",
"email": "alice@library.com",
"borrowed_books": []
}
]
}그리고 다음과 같이 입력하면:
1
B100
Design Patterns
Gang of Four
978-0201633610
0출력은 다음과 같아야 합니다:
{
"books": [
{
"id": "B100",
"title": "Design Patterns",
"author": "Gang of Four",
"isbn": "978-0201633610",
"available": true
}
],
"users": []
}중요: 슬라이스를 만들기 위해 맵을 순회할 때, 도서는 B001, B002 등의 순서(ID 기준 알파벳순 정렬)로 추가하고 사용자도 마찬가지로 추가하세요. 이렇게 하면 일관된 JSON 출력이 보장됩니다. 순회하기 전에 맵 키에 sort.Strings를 사용할 수 있습니다.
LibraryData 구조체는 맵 기반 저장소와 JSON의 배열 기반 형식 사이의 간극을 메워줍니다. 이러한 전송 객체(Transfer Object) 패턴은 복잡한 데이터 구조를 직렬화할 때 흔히 사용됩니다!
직접 해보기
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// 새로운 도서관 생성
library := NewLibrary()
// 도서 수 읽기
numBooksStr, _ := reader.ReadString('\n')
numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))
// TODO: 각 도서의 상세 정보(ID, title, author, ISBN) 읽기
// 그리고 도서관에 추가
for i := 0; i < numBooks; i++ {
// TODO: 도서 ID 읽기
// TODO: 도서 제목 읽기
// TODO: 도서 저자 읽기
// TODO: 도서 ISBN 읽기
// TODO: 도서 생성 및 도서관에 추가
}
// 사용자 수 읽기
numUsersStr, _ := reader.ReadString('\n')
numUsers, _ := strconv.Atoi(strings.TrimSpace(numUsersStr))
// TODO: 각 사용자의 상세 정보(ID, name, email) 읽기
// 그리고 도서관에 추가
for i := 0; i < numUsers; i++ {
// TODO: 사용자 ID 읽기
// TODO: 사용자 이름 읽기
// TODO: 사용자 이메일 읽기
// TODO: 사용자 생성 및 도서관에 추가
}
// TODO: 도서관 정보를 JSON으로 변환하고 출력하기
fmt.Println(library.ToJSON())
}
객체 지향 프로그래밍의 모든 레슨
8에러 처리와 OOP
error 인터페이스사용자 정의 에러 타입에러 래핑 (fmt.Errorf)센티넬 에러errors.Is()와 errors.As()Panic, Defer, Recover요약 - 파일 파서