E-Learning-Plattform
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy. Lektion 105 von 107.
Aufgabe
EinfachLass uns eine E-Learning-Plattform erstellen, die Kurse und Studierende verwaltet und den Lernfortschritt verfolgt! Du wirst Structs, Interfaces, Komposition und Polymorphismus kombinieren, um ein zusammenhängendes System zu erstellen, in dem sich Studierende für Kurse einschreiben und Lektionen abschließen können.
Du wirst deinen Code auf fünf Dateien verteilen:
lesson.go: Definiere einLesson-Struct, das einzelne Lerneinheiten repräsentiert. Jede Lektion hat eineID, einenTitleund eineDuration(in Minuten). Füge einenNewLesson-Konstruktor hinzu, der einen Zeiger auf ein Lesson zurückgibt.course.go: Erstelle einCourse-Struct, das eineID, einenTitle, einenInstructorund ein Slice mit*Lesson-Zeigern enthält. Füge einenNewCourse-Konstruktor und eineAddLesson-Methode hinzu. Implementiere außerdem eineTotalDuration() int-Methode, die die Summe der Dauer aller Lektionen im Kurs zurückgibt.student.go: Definiere einStudent-Struct mit den FeldernID,NameundEmail. Füge einenNewStudent-Konstruktor hinzu.enrollment.go: Hier geschieht die Magie der Fortschrittsverfolgung. Erstelle einEnrollment-Struct, das einen Studierenden mit einem Kurs verknüpft und verfolgt, welche Lektionen abgeschlossen wurden. Es sollte Folgendes enthalten:- Einen Zeiger auf den
Student - Einen Zeiger auf den
Course - Eine
CompletedLessons-Map (Lektions-ID zu Boolean)
Definiere ein
Progressable-Interface mit einerProgress() float64-Methode, die einen Prozentsatz (0.0 bis 100.0) zurückgibt.Implementiere diese Methoden für Enrollment:
NewEnrollment(student *Student, course *Course) *Enrollment: Konstruktor, der eine leere Map für abgeschlossene Lektionen initialisiertCompleteLesson(lessonID string) string: Markiert eine Lektion als abgeschlossen. Gibtlesson not foundzurück, wenn die Lektion im Kurs nicht existiert,already completed, wenn sie bereits abgeschlossen wurde, oder bei ErfolgcompletedProgress() float64: Gibt den Prozentsatz der abgeschlossenen Lektionen zurück (abgeschlossen/gesamt * 100) oder 0.0, wenn der Kurs keine Lektionen enthält
- Einen Zeiger auf den
main.go: Erstelle deine Plattform und verarbeite Einschreibevorgänge.Lies die ID, den Titel und den Dozenten eines Kurses ein. Lies anschließend die Anzahl der Lektionen sowie die ID, den Titel und die Dauer jeder Lektion ein. Lies die ID, den Namen und die E-Mail-Adresse eines Studierenden ein. Erstelle eine Einschreibung, die den Studierenden mit dem Kurs verknüpft.
Lies anschließend die Anzahl der Vorgänge ein. Jeder Vorgang ist entweder
complete [lessonID]oderprogress. Gib bei Abschlussvorgängen die Ergebnismeldung aus. Gib bei Fortschrittsvorgängen den Fortschritt, auf eine Dezimalstelle formatiert, gefolgt von einem Prozentzeichen aus.
Die folgenden Eingaben werden bereitgestellt:
- Kurs-ID, Titel, Dozent (3 Zeilen)
- Anzahl der Lektionen, anschließend die ID, der Titel und die Dauer jeder Lektion (jeweils 3 Zeilen)
- Studierenden-ID, Name, E-Mail-Adresse (3 Zeilen)
- Anzahl der Vorgänge, anschließend jeder Vorgang (jeweils 1 Zeile)
Beispielweise bei folgenden Eingaben:
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 L002Deine Ausgabe sollte lauten:
0.0%
completed
33.3%
already completed
completedUnd bei folgenden Eingaben:
C100
Python Basics
Bob Teacher
2
L100
Intro
20
L101
Loops
40
S100
Charlie
charlie@edu.com
4
complete L999
complete L100
complete L101
progressDeine Ausgabe sollte lauten:
lesson not found
completed
completed
100.0%Beachte, wie das Enrollment-Struct Komposition verwendet, um Studierende und Kurse miteinander zu verknüpfen, während das Progressable-Interface es jedem Typ ermöglicht, seinen Abschlussstatus zu melden. Dieses Design lässt sich leicht erweitern. Du könntest mithilfe desselben Interfaces die Fortschrittsverfolgung auf einzelne Lektionen oder ganze Lernpfade ausweiten!
Probier es selbst
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Hilfsfunktion zum Lesen einer Zeile
readLine := func() string {
scanner.Scan()
return strings.TrimSpace(scanner.Text())
}
// Kursinformationen lesen
courseID := readLine()
courseTitle := readLine()
courseInstructor := readLine()
// TODO: Create the course using NewCourse
_ = courseID
_ = courseTitle
_ = courseInstructor
// Anzahl der Lektionen lesen
numLessons, _ := strconv.Atoi(readLine())
// TODO: Read each lesson and add to course
for i := 0; i < numLessons; i++ {
lessonID := readLine()
lessonTitle := readLine()
lessonDuration, _ := strconv.Atoi(readLine())
// TODO: Create lesson and add to course
_ = lessonID
_ = lessonTitle
_ = lessonDuration
}
// Studenteninformationen lesen
studentID := readLine()
studentName := readLine()
studentEmail := readLine()
// TODO: Create the student using NewStudent
_ = studentID
_ = studentName
_ = studentEmail
// TODO: Create enrollment linking student to course
// Anzahl der Operationen lesen
numOps, _ := strconv.Atoi(readLine())
// Jede Operation verarbeiten
for i := 0; i < numOps; i++ {
operation := readLine()
if operation == "progress" {
// TODO: Call Progress() and print with format "%.1f%%"
fmt.Println("0.0%") // Ersetze durch den tatsächlichen Fortschritt
} else if strings.HasPrefix(operation, "complete ") {
lessonID := strings.TrimPrefix(operation, "complete ")
// TODO: CompleteLesson aufrufen und das Ergebnis ausgeben
_ = lessonID
fmt.Println("") // Ersetze durch das tatsächliche Ergebnis
}
}
}
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP in Go
Externe DateienGo-Workspace & ModulePackages & ImportsExportierte vs. nicht exportierte NamenEinführung in OOP mit GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktorfunktionenRückblick – Einfacher Taschenrechner4Schnittstellen
Einführung in SchnittstellenImplizite ImplementierungSchnittstelle als VertragLeere Schnittstelle (any)TypzusicherungTypwechselZusammensetzung von SchnittstellenStringer- und Error-SchnittstellenRückblick – Formenrechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf PaketebeneGetter- und Setter-MethodenInformationsverbergung in GoRückblick – Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterTypbeschränkungenGenerische StrukturenWorkaround für generische MethodenZusammenfassung – Generische Sammlung2Typen & Structs im Detail
Grundlegende & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct-TagsAnonyme StructsVerschachtelte StructsNullwerte & StandardwerteRückblick – Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen der Struct-EinbettungMethoden-PromotionMehrere Structs einbettenEinbettung vs. AggregationVerbergen eingebetteter MethodenRückblick – Mitarbeiterhierarchie8Fehlerbehandlung & OOP
Das Error-InterfaceBenutzerdefinierte FehlertypenError-Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverRückblick – Dateiparser3Zeiger & Speicher
Grundlagen von Zeigern in GoZeiger auf StructsÜbergabe per Wert vs. ReferenzDie Funktion new()Garbage Collection in GoRückblick – Verkettete Liste erstellen6Polymorphismus in Go
Polymorphismus über InterfacesDuck-Typing in GoRegeln zur Interface-ErfüllungPolymorphe SammlungenDependency InjectionZusammenfassung – Zahlungsprozessor9Konkurrenz & OOP
Grundlagen der GoroutinesChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignRückblick – Worker PoolÜbe selbstständig: Online-Go-Compiler