E-Learning Platform
Part of the Object Oriented Programming section of Coddy's GO journey — lesson 105 of 107.
Challenge
EasyLet's build an E-Learning Platform that manages courses, students, and tracks learning progress! You'll combine structs, interfaces, composition, and polymorphism to create a cohesive system where students can enroll in courses and complete lessons.
You'll organize your code across five files:
lesson.go: Define aLessonstruct representing individual learning units. Each lesson has anID,Title, andDuration(in minutes). Include aNewLessonconstructor that returns a pointer to a Lesson.course.go: Create aCoursestruct that contains anID,Title,Instructor, and a slice of*Lessonpointers. Include aNewCourseconstructor and anAddLessonmethod. Also implement aTotalDuration() intmethod that returns the sum of all lesson durations in the course.student.go: Define aStudentstruct withID,Name, andEmailfields. Include aNewStudentconstructor.enrollment.go: This is where the progress tracking magic happens. Create anEnrollmentstruct that links a student to a course and tracks which lessons they've completed. It should have:- A pointer to the
Student - A pointer to the
Course - A
CompletedLessonsmap (lesson ID to boolean)
Define a
Progressableinterface with aProgress() float64method that returns a percentage (0.0 to 100.0).Implement these methods on Enrollment:
NewEnrollment(student *Student, course *Course) *Enrollment— constructor that initializes an empty completed lessons mapCompleteLesson(lessonID string) string— marks a lesson complete. Returnslesson not foundif the lesson doesn't exist in the course,already completedif already done, orcompletedon successProgress() float64— returns the percentage of lessons completed (completed/total * 100), or 0.0 if the course has no lessons
- A pointer to the
main.go: Build your platform and process enrollment operations.Read a course's ID, title, and instructor. Then read the number of lessons and each lesson's ID, title, and duration. Read a student's ID, name, and email. Create an enrollment linking the student to the course.
Then read the number of operations. Each operation is either
complete [lessonID]orprogress. For complete operations, print the result message. For progress operations, print the progress formatted to one decimal place followed by a percent sign.
The following inputs will be provided:
- Course ID, Title, Instructor (3 lines)
- Number of lessons, then each lesson's ID, Title, Duration (3 lines each)
- Student ID, Name, Email (3 lines)
- Number of operations, then each operation (1 line each)
For example, given:
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 L002Your output should be:
0.0%
completed
33.3%
already completed
completedAnd given:
C100
Python Basics
Bob Teacher
2
L100
Intro
20
L101
Loops
40
S100
Charlie
charlie@edu.com
4
complete L999
complete L100
complete L101
progressYour output should be:
lesson not found
completed
completed
100.0%Notice how the Enrollment struct uses composition to link students and courses together, while the Progressable interface allows any type to report its completion status. This design makes it easy to extend—you could add progress tracking to individual lessons or entire learning paths using the same interface!
Try it yourself
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Helper function to read a line
readLine := func() string {
scanner.Scan()
return strings.TrimSpace(scanner.Text())
}
// Read course information
courseID := readLine()
courseTitle := readLine()
courseInstructor := readLine()
// TODO: Create the course using NewCourse
_ = courseID
_ = courseTitle
_ = courseInstructor
// Read number of lessons
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
}
// Read student information
studentID := readLine()
studentName := readLine()
studentEmail := readLine()
// TODO: Create the student using NewStudent
_ = studentID
_ = studentName
_ = studentEmail
// TODO: Create enrollment linking student to course
// Read number of operations
numOps, _ := strconv.Atoi(readLine())
// Process each operation
for i := 0; i < numOps; i++ {
operation := readLine()
if operation == "progress" {
// TODO: Call Progress() and print with format "%.1f%%"
fmt.Println("0.0%") // Replace with actual progress
} else if strings.HasPrefix(operation, "complete ") {
lessonID := strings.TrimPrefix(operation, "complete ")
// TODO: Call CompleteLesson and print the result
_ = lessonID
fmt.Println("") // Replace with actual result
}
}
}
All lessons in Object Oriented Programming
1Fundamentals of Go OOP
External FilesGo Workspace & ModulesPackages & ImportsExported vs Unexported NamesIntroduction to OOP in GoStructs as ClassesDefining Methods on StructsPointer vs Value ReceiversStruct InitializationConstructor FunctionsRecap - Simple Calculator4Interfaces
Introduction to InterfacesImplicit ImplementationInterface as ContractEmpty Interface (any)Type AssertionType SwitchInterface CompositionStringer & Error InterfacesRecap - Shape Calculator7Encapsulation
Exported vs Unexported FieldsPackage-Level EncapsulationGetter & Setter MethodsInformation Hiding in GoRecap - Student Records10Generics (Go 1.18+)
Introduction to GenericsType ParametersType ConstraintsGeneric StructsGeneric Methods WorkaroundRecap - Generic Collection2Types & Structs Deep Dive
Basic & Composite TypesCustom Type DefinitionsStruct TagsAnonymous StructsNested StructsZero Values & DefaultsRecap - Contact Book5Composition Over Inheritance
Why Go Has No InheritanceStruct Embedding BasicsMethod PromotionEmbedding Multiple StructsEmbedding vs AggregationShadowing Embedded MethodsRecap - Employee Hierarchy8Error Handling & OOP
The error InterfaceCustom Error TypesError Wrapping (fmt.Errorf)Sentinel Errorserrors.Is() and errors.As()Panic, Defer, and RecoverRecap - File Parser3Pointers & Memory
Pointer Basics in GoPointers to StructsPass by Value vs ReferenceThe new() FunctionGarbage Collection in GoRecap - Linked List Builder6Polymorphism in Go
Polymorphism via InterfacesDuck Typing in GoInterface Satisfaction RulesPolymorphic CollectionsDependency InjectionRecap - Payment Processor9Concurrency & OOP
Goroutines BasicsChannels & CommunicationBuffered vs Unbuffered ChanSelect Statementsync.Mutex & sync.RWMutexsync.WaitGroupThread-Safe Struct DesignRecap - Worker Pool