Platforma e-learningowa
Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 105 z 107.
Wyzwanie
ŁatwyZbudujmy platformę e-learningową, która zarządza kursami i studentami oraz śledzi postępy w nauce! Połączysz struktury, interfejsy, kompozycję i polimorfizm, aby stworzyć spójny system, w którym studenci mogą zapisywać się na kursy i zaliczać lekcje.
Rozmieścisz swój kod w pięciu plikach:
lesson.go: Zdefiniuj strukturęLesson, która reprezentuje poszczególne jednostki nauki. Każda lekcja maID,TitleiDuration(w minutach). Dodaj konstruktorNewLesson, który zwraca wskaźnik do obiektu Lesson.course.go: Utwórz strukturęCourse, która zawieraID,Title,Instructororaz wycinek wskaźników*Lesson. Dodaj konstruktorNewCoursei metodęAddLesson. Zaimplementuj też metodęTotalDuration() int, która zwraca sumę czasów trwania wszystkich lekcji w kursie.student.go: Zdefiniuj strukturęStudentz polamiID,NameiEmail. Dodaj konstruktorNewStudent.enrollment.go: Tu dzieje się magia śledzenia postępów. Utwórz strukturęEnrollment, która łączy studenta z kursem i śledzi, które lekcje zostały przez niego ukończone. Powinna zawierać:- Wskaźnik do
Student - Wskaźnik do
Course - Mapę
CompletedLessons(ID lekcji jako klucz, wartość logiczna jako wartość)
Zdefiniuj interfejs
Progressablez metodąProgress() float64, która zwraca procent (od 0.0 do 100.0).Zaimplementuj następujące metody dla Enrollment:
NewEnrollment(student *Student, course *Course) *Enrollment: konstruktor, który inicjalizuje pustą mapę ukończonych lekcjiCompleteLesson(lessonID string) string: oznacza lekcję jako ukończoną. Zwracalesson not found, jeśli lekcja nie istnieje w kursie,already completed, jeśli została już ukończona, albocompletedw przypadku powodzeniaProgress() float64: zwraca procent ukończonych lekcji (ukończone/łącznie * 100) lub 0.0, jeśli kurs nie zawiera lekcji
- Wskaźnik do
main.go: Zbuduj swoją platformę i przetwarzaj operacje związane z zapisami na kurs.Wczytaj ID, tytuł i instruktora kursu. Następnie wczytaj liczbę lekcji oraz ID, tytuł i czas trwania każdej lekcji. Wczytaj ID, imię i nazwisko oraz adres e-mail studenta. Utwórz zapis łączący studenta z kursem.
Następnie wczytaj liczbę operacji. Każda operacja to
complete [lessonID]alboprogress. W przypadku operacji complete wyświetl komunikat z wynikiem. W przypadku operacji progress wyświetl postęp sformatowany do jednego miejsca po przecinku, a następnie znak procentu.
Dane wejściowe będą podawane w następującej kolejności:
- ID kursu, tytuł, instruktor (3 wiersze)
- Liczba lekcji, a następnie ID, tytuł i czas trwania każdej lekcji (po 3 wiersze)
- ID, imię i nazwisko oraz adres e-mail studenta (3 wiersze)
- Liczba operacji, a następnie każda operacja (po 1 wierszu)
Na przykład dla danych:
C001
Go Fundamentals
Jane Smith
3
L001
Variables
30
L002
Functions
45
L003
Structs
60
S001
Alice
alice@learn.com
5
progress
complete L001
progress
complete L001
complete L002Oczekiwany wynik to:
0.0%
completed
33.3%
already completed
completedA dla danych:
C100
Python Basics
Bob Teacher
2
L100
Intro
20
L101
Loops
40
S100
Charlie
charlie@edu.com
4
complete L999
complete L100
complete L101
progressOczekiwany wynik to:
lesson not found
completed
completed
100.0%Zwróć uwagę, jak struktura Enrollment wykorzystuje kompozycję do łączenia studentów i kursów, a interfejs Progressable pozwala dowolnemu typowi raportować stan ukończenia. Dzięki takiemu projektowi łatwo rozszerzyć system. Możesz dodać śledzenie postępów dla pojedynczych lekcji lub całych ścieżek nauki, korzystając z tego samego interfejsu!
Spróbuj swoich sił
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Funkcja pomocnicza do odczytu wiersza
readLine := func() string {
scanner.Scan()
return strings.TrimSpace(scanner.Text())
}
// Odczytaj informacje o kursie
courseID := readLine()
courseTitle := readLine()
courseInstructor := readLine()
// TODO: Utwórz kurs za pomocą NewCourse
_ = courseID
_ = courseTitle
_ = courseInstructor
// Odczytaj liczbę lekcji
numLessons, _ := strconv.Atoi(readLine())
// TODO: Odczytaj każdą lekcję i dodaj ją do kursu
for i := 0; i < numLessons; i++ {
lessonID := readLine()
lessonTitle := readLine()
lessonDuration, _ := strconv.Atoi(readLine())
// TODO: Utwórz lekcję i dodaj ją do kursu
_ = lessonID
_ = lessonTitle
_ = lessonDuration
}
// Odczytaj informacje o uczniu
studentID := readLine()
studentName := readLine()
studentEmail := readLine()
// TODO: Utwórz ucznia za pomocą NewStudent
_ = studentID
_ = studentName
_ = studentEmail
// TODO: Utwórz zapis łączący ucznia z kursem
// Odczytaj liczbę operacji
numOps, _ := strconv.Atoi(readLine())
// Przetwórz każdą operację
for i := 0; i < numOps; i++ {
operation := readLine()
if operation == "progress" {
// TODO: Wywołaj Progress() i wypisz wynik w formacie "%.1f%%"
fmt.Println("0.0%") // Zastąp rzeczywistym postępem
} else if strings.HasPrefix(operation, "complete ") {
lessonID := strings.TrimPrefix(operation, "complete ")
// TODO: Wywołaj CompleteLesson i wypisz wynik
_ = lessonID
fmt.Println("") // Zastąp rzeczywistym wynikiem
}
}
}
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 koduPoćwicz samodzielnie: Kompilator Go online