E-Learning-Plattform
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 105 von 107.
Aufgabe
EinfachLassen Sie uns eine E-Learning-Plattform bauen, die Kurse und Studenten verwaltet und den Lernfortschritt verfolgt! Sie werden Structs, Interfaces, Komposition und Polymorphismus kombinieren, um ein zusammenhängendes System zu erstellen, in dem sich Studenten für Kurse einschreiben und Lektionen abschließen können.
Sie werden Ihren Code über fünf Dateien organisieren:
lesson.go: Definieren Sie einLesson-Struct, das einzelne Lerneinheiten darstellt. Jede Lektion hat eineID, einenTitleund eineDuration(in Minuten). Fügen Sie einenNewLesson-Konstruktor hinzu, der einen Pointer auf eine Lesson zurückgibt.course.go: Erstellen Sie einCourse-Struct, das eineID, einenTitle, einenInstructorund ein Slice von*Lesson-Pointern enthält. Fügen Sie einenNewCourse-Konstruktor und eineAddLesson-Methode hinzu. Implementieren Sie außerdem eineTotalDuration() int-Methode, die die Summe aller Lektionsdauern im Kurs zurückgibt.student.go: Definieren Sie einStudent-Struct mit den FeldernID,NameundEmail. Fügen Sie einenNewStudent-Konstruktor hinzu.enrollment.go: Hier findet die Magie der Fortschrittsverfolgung statt. Erstellen Sie einEnrollment-Struct, das einen Studenten mit einem Kurs verknüpft und verfolgt, welche Lektionen er abgeschlossen hat. Es sollte Folgendes haben:- Einen Pointer auf den
Student - Einen Pointer auf den
Course - Eine
CompletedLessons-Map (Lektions-ID zu Boolean)
Definieren Sie ein
Progressable-Interface mit einerProgress() float64-Methode, die einen Prozentsatz (0.0 bis 100.0) zurückgibt.Implementieren Sie 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, odercompletedbei ErfolgProgress() float64— gibt den Prozentsatz der abgeschlossenen Lektionen zurück (abgeschlossen/gesamt * 100) oder 0.0, wenn der Kurs keine Lektionen hat
- Einen Pointer auf den
main.go: Bauen Sie Ihre Plattform und verarbeiten Sie Einschreibungsoperationen.Lesen Sie die ID, den Titel und den Kursleiter eines Kurses ein. Lesen Sie dann die Anzahl der Lektionen und die ID, den Titel und die Dauer jeder Lektion ein. Lesen Sie die ID, den Namen und die E-Mail eines Studenten ein. Erstellen Sie eine Einschreibung (Enrollment), die den Studenten mit dem Kurs verknüpft.
Lesen Sie dann die Anzahl der Operationen ein. Jede Operation ist entweder
complete [lessonID]oderprogress. Geben Sie bei complete-Operationen die Ergebnismeldung aus. Geben Sie bei progress-Operationen den Fortschritt formatiert auf eine Dezimalstelle gefolgt von einem Prozentzeichen aus.
Die folgenden Eingaben werden bereitgestellt:
- Kurs-ID, Titel, Kursleiter (3 Zeilen)
- Anzahl der Lektionen, dann ID, Titel, Dauer jeder Lektion (jeweils 3 Zeilen)
- Studenten-ID, Name, E-Mail (3 Zeilen)
- Anzahl der Operationen, dann jede Operation (jeweils 1 Zeile)
Zum Beispiel, gegeben:
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 L002Ihre Ausgabe sollte sein:
0.0%
completed
33.3%
already completed
completedUnd gegeben:
C100
Python Basics
Bob Teacher
2
L100
Intro
20
L101
Loops
40
S100
Charlie
charlie@edu.com
4
complete L999
complete L100
complete L101
progressIhre Ausgabe sollte sein:
lesson not found
completed
completed
100.0%Beachten Sie, wie das Enrollment-Struct Komposition verwendet, um Studenten und Kurse miteinander zu verknüpfen, während das Progressable-Interface es jedem Typ ermöglicht, seinen Abschlussstatus zu melden. Dieses Design macht es einfach zu erweitern — Sie könnten die Fortschrittsverfolgung für einzelne Lektionen oder ganze Lernpfade über dasselbe Interface hinzufügen!
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: Den Kurs mit NewCourse erstellen
_ = courseID
_ = courseTitle
_ = courseInstructor
// Anzahl der Lektionen lesen
numLessons, _ := strconv.Atoi(readLine())
// TODO: Jede Lektion lesen und zum Kurs hinzufügen
for i := 0; i < numLessons; i++ {
lessonID := readLine()
lessonTitle := readLine()
lessonDuration, _ := strconv.Atoi(readLine())
// TODO: Lektion erstellen und zum Kurs hinzufügen
_ = lessonID
_ = lessonTitle
_ = lessonDuration
}
// Studenteninformationen lesen
studentID := readLine()
studentName := readLine()
studentEmail := readLine()
// TODO: Den Studenten mit NewStudent erstellen
_ = studentID
_ = studentName
_ = studentEmail
// TODO: Einschreibung erstellen, die den Studenten mit dem Kurs verknüpft
// Anzahl der Operationen lesen
numOps, _ := strconv.Atoi(readLine())
// Jede Operation verarbeiten
for i := 0; i < numOps; i++ {
operation := readLine()
if operation == "progress" {
// TODO: Progress() aufrufen und im Format "%.1f%%" ausgeben
fmt.Println("0.0%") // Durch tatsächlichen Fortschritt ersetzen
} else if strings.HasPrefix(operation, "complete ") {
lessonID := strings.TrimPrefix(operation, "complete ")
// TODO: CompleteLesson aufrufen und das Ergebnis ausgeben
_ = lessonID
fmt.Println("") // Durch tatsächliches Ergebnis ersetzen
}
}
}
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der Go OOP
Externe DateienGo Workspace & ModulePackages & ImportsExportierte vs. nicht-exportierte NamenEinführung in OOP in GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktor-FunktionenZusammenfassung – Einfacher Taschenrechner4Interfaces
Einführung in InterfacesImplizite ImplementierungInterface als VertragLeeres Interface (any)Type AssertionType SwitchInterface-KompositionStringer & Error InterfacesRückblick - Formen-Rechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf Paket-EbeneGetter- & Setter-MethodenInformation Hiding in GoZusammenfassung - Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterType ConstraintsGenerische StructsWorkaround für generische MethodenZusammenfassung – Generische Collection2Vertiefung: Typen & Structs
Basis- & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct TagsAnonyme StructsVerschachtelte StructsZero Values & StandardwerteZusammenfassung - Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen des Struct EmbeddingMethod PromotionEinbetten mehrerer StructsEmbedding vs. AggregationShadowing eingebetteter MethodenZusammenfassung – Mitarbeiter-Hierarchie8Fehlerbehandlung & OOP
Das error-InterfaceEigene FehlertypenError Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverZusammenfassung – Datei-Parser3Zeiger & Speicher
Zeiger-Grundlagen in GoZeiger auf StructsWertübergabe vs. ReferenzübergabeDie new() FunktionGarbage Collection in GoWiederholung – Linked List Builder6Polymorphismus in Go
Polymorphismus über InterfacesDuck Typing in GoInterface-ErfüllungsregelnPolymorphe CollectionsDependency InjectionZusammenfassung – Payment Processor9Nebenläufigkeit & OOP
Goroutines GrundlagenChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignZusammenfassung - Worker Pool