Plataforma de E-Learning
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy — lição 105 de 107.
Desafio
FácilVamos construir uma Plataforma de E-Learning que gerencia cursos, alunos e rastreia o progresso de aprendizado! Você combinará structs, interfaces, composição e polimorfismo para criar um sistema coeso onde os alunos podem se matricular em cursos e concluir lições.
Você organizará seu código em cinco arquivos:
lesson.go: Defina uma structLessonrepresentando unidades de aprendizado individuais. Cada lição tem umID,TitleeDuration(em minutos). Inclua um construtorNewLessonque retorna um ponteiro para uma Lesson.course.go: Crie uma structCourseque contém umID,Title,Instructore um slice de ponteiros*Lesson. Inclua um construtorNewCoursee um métodoAddLesson. Também implemente um métodoTotalDuration() intque retorna a soma de todas as durações das lições no curso.student.go: Defina uma structStudentcom os camposID,NameeEmail. Inclua um construtorNewStudent.enrollment.go: É aqui que a mágica do rastreamento de progresso acontece. Crie uma structEnrollmentque vincula um aluno a um curso e rastreia quais lições eles concluíram. Ela deve ter:- Um ponteiro para o
Student - Um ponteiro para o
Course - Um mapa
CompletedLessons(ID da lição para booleano)
Defina uma interface
Progressablecom um métodoProgress() float64que retorna uma porcentagem (0.0 a 100.0).Implemente estes métodos em Enrollment:
NewEnrollment(student *Student, course *Course) *Enrollment— construtor que inicializa um mapa de lições concluídas vazioCompleteLesson(lessonID string) string— marca uma lição como concluída. Retorna"lesson not found"se a lição não existir no curso,"already completed"se já estiver concluída, ou"completed"em caso de sucessoProgress() float64— retorna a porcentagem de lições concluídas (concluídas/total * 100), ou 0.0 se o curso não tiver lições
- Um ponteiro para o
main.go: Construa sua plataforma e processe as operações de matrícula.Leia o ID, título e instrutor de um curso. Em seguida, leia o número de lições e o ID, título e duração de cada lição. Leia o ID, nome e e-mail de um aluno. Crie uma matrícula vinculando o aluno ao curso.
Depois, leia o número de operações. Cada operação é
"complete [lessonID]"ou"progress". Para operações complete, imprima a mensagem de resultado. Para operações progress, imprima o progresso formatado com uma casa decimal seguido por um sinal de porcentagem.
As seguintes entradas serão fornecidas:
- ID do Curso, Título, Instrutor (3 linhas)
- Número de lições, então o ID, Título e Duração de cada lição (3 linhas cada)
- ID do Aluno, Nome, E-mail (3 linhas)
- Número de operações, então cada operação (1 linha cada)
Por exemplo, dado:
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 L002Sua saída deve ser:
0.0%
completed
33.3%
already completed
completedE dado:
C100
Python Basics
Bob Teacher
2
L100
Intro
20
L101
Loops
40
S100
Charlie
charlie@edu.com
4
complete L999
complete L100
complete L101
progressSua saída deve ser:
lesson not found
completed
completed
100.0%Observe como a struct Enrollment usa composição para vincular alunos e cursos, enquanto a interface Progressable permite que qualquer tipo relate seu status de conclusão. Este design facilita a extensão — você poderia adicionar rastreamento de progresso a lições individuais ou trilhas de aprendizado inteiras usando a mesma interface!
Experimente você mesmo
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Função auxiliar para ler uma linha
readLine := func() string {
scanner.Scan()
return strings.TrimSpace(scanner.Text())
}
// Ler informações do curso
courseID := readLine()
courseTitle := readLine()
courseInstructor := readLine()
// TODO: Criar o curso usando NewCourse
_ = courseID
_ = courseTitle
_ = courseInstructor
// Ler o número de lições
numLessons, _ := strconv.Atoi(readLine())
// TODO: Ler cada lição e adicionar ao curso
for i := 0; i < numLessons; i++ {
lessonID := readLine()
lessonTitle := readLine()
lessonDuration, _ := strconv.Atoi(readLine())
// TODO: Criar lição e adicionar ao curso
_ = lessonID
_ = lessonTitle
_ = lessonDuration
}
// Ler informações do aluno
studentID := readLine()
studentName := readLine()
studentEmail := readLine()
// TODO: Criar o aluno usando NewStudent
_ = studentID
_ = studentName
_ = studentEmail
// TODO: Criar a matrícula vinculando o aluno ao curso
// Ler o número de operações
numOps, _ := strconv.Atoi(readLine())
// Processar cada operação
for i := 0; i < numOps; i++ {
operation := readLine()
if operation == "progress" {
// TODO: Chamar Progress() e imprimir com o formato "%.1f%%"
fmt.Println("0.0%") // Substituir pelo progresso real
} else if strings.HasPrefix(operation, "complete ") {
lessonID := strings.TrimPrefix(operation, "complete ")
// TODO: Chamar CompleteLesson e imprimir o resultado
_ = lessonID
fmt.Println("") // Substituir pelo resultado real
}
}
}
Todas as lições de Programação Orientada a Objetos
1Fundamentos de OOP em Go
Arquivos ExternosGo Workspace e MódulosPacotes e ImportaçõesNomes Exportados vs Não ExportadosIntrodução a OOP em GoStructs como ClassesDefinindo Métodos em StructsRecebedores de Ponteiro vs ValorInicialização de StructsFunções ConstrutorasRecapitulação - Calculadora Simples4Interfaces
Introdução a InterfacesImplementação ImplícitaInterface como ContratoInterface Vazia (any)Type AssertionType SwitchComposição de InterfacesInterfaces Stringer & ErrorRecapitulação - Calculadora de Formas7Encapsulamento
Campos Exportados vs Não ExportadosEncapsulamento em Nível de PacoteMétodos Getter e SetterOcultação de Informação em GoRecapitulação - Registros de Estudantes10Generics (Go 1.18+)
Introdução a GenericsParâmetros de TipoRestrições de TipoStructs GenéricasSolução Alternativa para Métodos GenéricosRecapitulação - Coleção Genérica2Mergulho Profundo em Tipos e Structs
Tipos Básicos e CompostosDefinições de Tipos PersonalizadosStruct TagsStructs AnônimasStructs AninhadasZero Values e PadrõesRecapitulação - Agenda de Contatos5Composição em vez de Herança
Por que Go não possui HerançaFundamentos de Incorporação de StructsPromoção de MétodosIncorporando Múltiplas StructsIncorporação vs AgregaçãoShadowing de Métodos IncorporadosRecapitulação - Hierarquia de Funcionários8Tratamento de Erros e OOP
A Interface errorTipos de Erro PersonalizadosError Wrapping (fmt.Errorf)Erros Sentinelaerrors.Is() e errors.As()Panic, Defer e RecoverRecapitulação - File Parser3Ponteiros e Memória
Fundamentos de Ponteiros em GoPonteiros para StructsPassagem por Valor vs ReferênciaA Função new()Garbage Collection em GoRecapitulação - Construtor de Lista Encadeada6Polimorfismo em Go
Polimorfismo via InterfacesDuck Typing em GoRegras de Satisfação de InterfaceColeções PolimórficasInjeção de DependênciaRecapitulação - Processador de Pagamentos9Concorrência e OOP
Fundamentos de GoroutinesCanais e ComunicaçãoCanais com Buffer vs. Sem BufferInstrução Selectsync.Mutex e sync.RWMutexsync.WaitGroupDesign de Structs Thread-SafeRecapitulação - Worker Pool