Piattaforma di e-learning
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 105 di 107.
Sfida
FacileCostruiamo una piattaforma di e-learning che gestisce corsi e studenti e tiene traccia dei progressi di apprendimento! Combinerai struct, interfacce, composizione e polimorfismo per creare un sistema coerente in cui gli studenti possono iscriversi ai corsi e completare le lezioni.
Organizzerai il codice in cinque file:
lesson.go: Definisci una structLessonche rappresenta singole unità di apprendimento. Ogni lezione ha unID, unTitlee unaDuration(in minuti). Includi un costruttoreNewLessonche restituisce un puntatore a una Lesson.course.go: Crea una structCourseche contiene unID, unTitle, unInstructore uno slice di puntatori*Lesson. Includi un costruttoreNewCoursee un metodoAddLesson. Implementa anche un metodoTotalDuration() intche restituisce la somma delle durate di tutte le lezioni del corso.student.go: Definisci una structStudentcon i campiID,NameeEmail. Includi un costruttoreNewStudent.enrollment.go: È qui che avviene la magia del monitoraggio dei progressi. Crea una structEnrollmentche collega uno studente a un corso e tiene traccia delle lezioni completate. Dovrebbe avere:- Un puntatore a
Student - Un puntatore a
Course - Una mappa
CompletedLessons(ID della lezione associato a un valore booleano)
Definisci un'interfaccia
Progressablecon un metodoProgress() float64che restituisce una percentuale (da 0.0 a 100.0).Implementa questi metodi su Enrollment:
NewEnrollment(student *Student, course *Course) *Enrollment: costruttore che inizializza una mappa vuota delle lezioni completateCompleteLesson(lessonID string) string: contrassegna una lezione come completata. Restituiscelesson not foundse la lezione non esiste nel corso,already completedse è già stata completata, oppurecompletedin caso di successoProgress() float64: restituisce la percentuale di lezioni completate (completate/totali * 100), oppure 0.0 se il corso non ha lezioni
- Un puntatore a
main.go: Crea la tua piattaforma e gestisci le operazioni di iscrizione.Leggi l'ID, il titolo e l'istruttore di un corso. Poi leggi il numero di lezioni e l'ID, il titolo e la durata di ciascuna lezione. Leggi l'ID, il nome e l'indirizzo email di uno studente. Crea un'iscrizione che colleghi lo studente al corso.
Poi leggi il numero di operazioni. Ogni operazione è
complete [lessonID]oppureprogress. Per le operazioni di completamento, stampa il messaggio del risultato. Per le operazioni di avanzamento, stampa il progresso formattato con una cifra decimale, seguito dal simbolo di percentuale.
Verranno forniti i seguenti input:
- ID del corso, titolo, istruttore (3 righe)
- Numero di lezioni, poi ID, titolo e durata di ogni lezione (3 righe ciascuna)
- ID, nome e indirizzo email dello studente (3 righe)
- Numero di operazioni, poi ogni operazione (1 riga ciascuna)
Ad esempio, dato:
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 L002Il tuo output dovrebbe essere:
0.0%
completed
33.3%
already completed
completedE dato:
C100
Python Basics
Bob Teacher
2
L100
Intro
20
L101
Loops
40
S100
Charlie
charlie@edu.com
4
complete L999
complete L100
complete L101
progressIl tuo output dovrebbe essere:
lesson not found
completed
completed
100.0%Nota come la struct Enrollment usa la composizione per collegare studenti e corsi, mentre l'interfaccia Progressable permette a qualsiasi tipo di comunicare il proprio stato di completamento. Questo design è facile da estendere. Potresti aggiungere il monitoraggio dei progressi a singole lezioni o a interi percorsi di apprendimento usando la stessa interfaccia!
Provalo tu
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Funzione di supporto per leggere una riga
readLine := func() string {
scanner.Scan()
return strings.TrimSpace(scanner.Text())
}
// Leggi le informazioni sul corso
courseID := readLine()
courseTitle := readLine()
courseInstructor := readLine()
// TODO: Crea il corso usando NewCourse
_ = courseID
_ = courseTitle
_ = courseInstructor
// Leggi il numero di lezioni
numLessons, _ := strconv.Atoi(readLine())
// TODO: Leggi ogni lezione e aggiungila al corso
for i := 0; i < numLessons; i++ {
lessonID := readLine()
lessonTitle := readLine()
lessonDuration, _ := strconv.Atoi(readLine())
// TODO: Crea la lezione e aggiungila al corso
_ = lessonID
_ = lessonTitle
_ = lessonDuration
}
// Leggi le informazioni sullo studente
studentID := readLine()
studentName := readLine()
studentEmail := readLine()
// TODO: Crea lo studente usando NewStudent
_ = studentID
_ = studentName
_ = studentEmail
// TODO: Crea l'iscrizione che collega lo studente al corso
// Leggi il numero di operazioni
numOps, _ := strconv.Atoi(readLine())
// Elabora ogni operazione
for i := 0; i < numOps; i++ {
operation := readLine()
if operation == "progress" {
// TODO: Chiama Progress() e stampa nel formato "%.1f%%"
fmt.Println("0.0%") // Sostituisci con l'avanzamento effettivo
} else if strings.HasPrefix(operation, "complete ") {
lessonID := strings.TrimPrefix(operation, "complete ")
// TODO: Chiama CompleteLesson e stampa il risultato
_ = lessonID
fmt.Println("") // Sostituisci con il risultato effettivo
}
}
}
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti di OOP in Go
File esterniWorkspace e moduli GoPacchetti e importazioniNomi esportati e non esportatiIntroduzione all’OOP in GoGli struct come classiDefinire metodi sugli structReceiver con puntatore vs receiver con valoreInizializzazione degli structFunzioni costruttriciRiepilogo - Calcolatrice semplice4Interfacce
Introduzione alle interfacceImplementazione implicitaL’interfaccia come contrattoInterfaccia vuota (any)Asserzione di tipoSwitch sul tipoComposizione di interfacceInterfacce Stringer ed ErrorRipasso - Calcolatore di forme7Incapsulamento
Campi esportati e non esportatiIncapsulamento a livello di packageMetodi Getter e SetterNascondimento delle informazioni in GoRiepilogo - Registri degli studenti10Tipi generici (Go 1.18+)
Introduzione ai tipi genericiParametri di tipoVincoli di tipoStruct genericheSoluzione alternativa per i metodi genericiRiepilogo - Collezione generica13Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneModello SingletonModello FactoryModello Abstract FactoryModello ObserverModello Strategy2Approfondimento su tipi e struct
Tipi di base e compostiDefinizioni di tipi personalizzatiTag delle structStruct anonimeStruct annidateValori zero e predefinitiRipasso - Rubrica5Composizione invece dell'ereditarietà
Perché Go non ha l'ereditarietàFondamenti dell'embedding delle structPromozione dei metodiEmbedding di più structEmbedding e aggregazione a confrontoMascheramento dei metodi embeddedRiepilogo: gerarchia dei dipendenti8Gestione degli errori e OOP
L'interfaccia errorTipi di errore personalizzatiWrapping degli errori (fmt.Errorf)Errori sentinellaerrors.Is() ed errors.As()Panic, Defer e RecoverRiepilogo - Parser di file11Libreria standard e OOP
io.Reader e io.Writersort.InterfaceInterfaccia fmt.Stringerencoding/json con le structInterfaccia http.HandlerRipasso - modelli REST API14Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeMiddleware come Decorator3Puntatori e memoria
Concetti base dei puntatori in GoPuntatori a structPassaggio per valore vs per riferimentoLa funzione new()Garbage collection in GoRiepilogo - Costruttore di liste concatenate6Polimorfismo in Go
Polimorfismo tramite interfacceDuck typing in GoRegole di soddisfacimento delle interfacceCollezioni polimorficheIniezione delle dipendenzeRiepilogo - Elaboratore di pagamenti9Concorrenza e OOP
Basi delle goroutineCanali e comunicazioneCanali bufferizzati vs non bufferizzatiIstruzione selectsync.Mutex e sync.RWMutexsync.WaitGroupProgettazione di struct thread-safeRiepilogo: worker poolEsercitati da solo: Compilatore Go online