Warstwa zapisu danych w JSON
Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 102 z 107.
Wyzwanie
ŁatwyDodajmy trwałość danych do naszego systemu zarządzania biblioteką! Zaimplementujesz warstwę trwałości JSON, która potrafi konwertować dane biblioteki do formatu JSON w celu ich zapisania, a następnie wczytywać je z powrotem z ciągów JSON. Jest to niezbędne w każdej rzeczywistej aplikacji, która musi zachowywać dane między sesjami.
Rozmieścisz kod w pięciu plikach:
book.go: Twoja strukturaBookz tagami JSON kontrolującymi serializację. Każde pole powinno mieć odpowiadający mu tag JSON:id,title,author,isbniavailable. Dodaj konstruktorNewBook.user.go: Twoja strukturaUserz tagami JSON dla pólid,name,emailiborrowed_books. Dodaj konstruktorNewUser.data.go: Utwórz strukturęLibraryData, która pełni rolę obiektu transferowego do serializacji JSON. Powinna mieć dwa pola:Books(tablicę wskaźników do Book) iUsers(tablicę wskaźników do User), każde z odpowiednimi tagami JSON (booksiusers).library.go: Twoja strukturaLibraryz mapami książek i użytkowników. Dodaj dwie nowe metody:ToJSON(): konwertuje dane biblioteki na sformatowany ciąg JSON za pomocąjson.MarshalIndentz wcięciem wynoszącym dwie spacje. Powinna zebrać wszystkie książki i użytkowników z map do strukturyLibraryData, a następnie przeprowadzić serializację.FromJSON(jsonStr string): przyjmuje ciąg JSON, deserializuje go do strukturyLibraryDatai wypełnia mapy biblioteki wczytanymi książkami i użytkownikami.
main.go: Zademonstruj działanie warstwy trwałości, tworząc bibliotekę i konwertując ją do JSON.Wczytaj liczbę książek, a następnie dla każdej książki wczytaj jej ID, tytuł, autora i ISBN. Następnie wczytaj liczbę użytkowników, a dla każdego użytkownika wczytaj jego ID, imię i adres e-mail. Po wypełnieniu biblioteki wywołaj
ToJSON()i wyświetl wynikowy ciąg JSON.
Zostaną podane następujące dane wejściowe:
- Liczba książek, a następnie ID, tytuł, autor i ISBN każdej książki (każda wartość w osobnym wierszu)
- Liczba użytkowników, a następnie ID, imię i adres e-mail każdego użytkownika (każda wartość w osobnym wierszu)
Na przykład, dla danych:
2
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Clean Code
Robert Martin
978-0132350884
1
U001
Alice Smith
alice@library.comWynik powinien być następujący:
{
"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": []
}
]
}A dla danych:
1
B100
Design Patterns
Gang of Four
978-0201633610
0Wynik powinien być następujący:
{
"books": [
{
"id": "B100",
"title": "Design Patterns",
"author": "Gang of Four",
"isbn": "978-0201633610",
"available": true
}
],
"users": []
}Ważne: Podczas iterowania po mapach w celu utworzenia tablic dodawaj książki w kolejności: B001, B002 itd. (posortowane alfabetycznie według ID), a użytkowników w podobny sposób. Zapewni to spójny wynik JSON. Możesz użyć sort.Strings na kluczach map przed iterowaniem.
Struktura LibraryData łączy przechowywanie danych w mapach z formatem JSON opartym na tablicach. Ten wzorzec obiektu transferowego jest często stosowany podczas serializacji złożonych struktur danych!
Spróbuj swoich sił
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Utwórz nową bibliotekę
library := NewLibrary()
// Odczytaj liczbę książek
numBooksStr, _ := reader.ReadString('\n')
numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))
// TODO: Odczytaj dane każdej książki (ID, tytuł, autor, ISBN)
// i dodaj je do biblioteki
for i := 0; i < numBooks; i++ {
// TODO: Odczytaj ID książki
// TODO: Odczytaj tytuł książki
// TODO: Odczytaj autora książki
// TODO: Odczytaj ISBN książki
// TODO: Utwórz książkę i dodaj ją do biblioteki
}
// Odczytaj liczbę użytkowników
numUsersStr, _ := reader.ReadString('\n')
numUsers, _ := strconv.Atoi(strings.TrimSpace(numUsersStr))
// TODO: Odczytaj dane każdego użytkownika (ID, imię, adres e-mail)
// i dodaj je do biblioteki
for i := 0; i < numUsers; i++ {
// TODO: Odczytaj ID użytkownika
// TODO: Wczytaj nazwę użytkownika
// TODO: Wczytaj adres e-mail użytkownika
// TODO: Utwórz użytkownika i dodaj go do biblioteki
}
// TODO: Przekształć bibliotekę na JSON i ją wyświetl
fmt.Println(library.ToJSON())
}
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy OOP w Go
Pliki zewnętrzneObszar roboczy i moduły GoPakiety i importyNazwy eksportowane i nieeksportowaneWprowadzenie do OOP w GoStruktury jako klasyDefiniowanie metod dla strukturOdbiorniki wskaźnikowe i wartościoweInicjalizacja strukturFunkcje konstruktoraPodsumowanie – prosty kalkulator4Interfejsy
Wprowadzenie do interfejsówImplementacja niejawnaInterfejs jako kontraktPusty interfejs (any)Asercja typuPrzełącznik typówKompozycja interfejsówInterfejsy Stringer i ErrorPowtórka — kalkulator figur7Hermetyzacja
Pola eksportowane i nieeksportowaneHermetyzacja na poziomie pakietuMetody pobierające i ustawiająceUkrywanie informacji w GoPowtórka – dane studentów10Typy generyczne (Go 1.18+)
Wprowadzenie do typów generycznychParametry typówOgraniczenia typówStruktury generyczneObejście ograniczeń metod generycznychPodsumowanie — generyczna kolekcja2Typy i struktury w praktyce
Typy proste i złożoneDefiniowanie własnych typówTagi pól strukturStruktury anonimoweStruktury zagnieżdżoneWartości zerowe i domyślnePodsumowanie – książka kontaktów5Kompozycja zamiast dziedziczenia
Dlaczego Go nie ma dziedziczeniaPodstawy osadzania strukturPromowanie metodOsadzanie wielu strukturOsadzanie a agregacjaPrzesłanianie osadzonych metodPodsumowanie — hierarchia pracowników8Obsługa błędów i programowanie obiektowe
Interfejs błęduWłasne typy błędówOpakowywanie błędów (fmt.Errorf)Błędy wartowniczeerrors.Is() i errors.As()Panic, Defer i RecoverPodsumowanie — parser plików3Wskaźniki i pamięć
Podstawy wskaźników w GoWskaźniki do strukturPrzekazywanie przez wartość a przez referencjęFunkcja new()Odśmiecanie pamięci w GoPowtórka — kreator listy wiązanej6Polimorfizm w Go
Polimorfizm za pomocą interfejsówDuck typing w GoZasady spełniania interfejsówKolekcje polimorficzneWstrzykiwanie zależnościPowtórka — procesor płatności9Współbieżność i OOP
Podstawy goroutinesKanały i komunikacjaKanały buforowane i niebuforowaneInstrukcja selectsync.Mutex i sync.RWMutexsync.WaitGroupProjektowanie struktur bezpiecznych wątkowoPowtórka – pula workerów12Zaawansowane zagadnienia programowania obiektowego
Wzorzec opcji funkcyjnychWzorzec Builder w GoŁańcuchowe wywoływanie metodAliasy typów a definicje typówPodstawy refleksjiPrzegląd generowania kodu15Projekt: Zarządzanie biblioteką
Przegląd i struktura projektuStruktury książek i użytkownikówPoćwicz samodzielnie: Kompilator Go online