Exercise 9 of 10 · Structs and methods
Playlist Runtime
What you will make
A playlist printout showing each song's length as minutes:seconds, plus the total runtime of the whole playlist.
The one new idea: Defining a struct with fields and a method on it (func (s Song) Format() string), used across a slice of structs
Structs with methods are how Go groups related data with the logic that acts on it, which is the shape most real Go code takes once programs grow past a handful of loose variables.
Go straight to the code ↓A type Song struct { Title string; Seconds int } groups related data into one value, and func (s Song) Format() string attaches behavior to it — inside the method, s refers to whichever Song value it was called on, so song.Format() runs the method with s bound to song. Splitting a duration into minutes and seconds is a classic use of two operators together: / gives you the whole minutes, and % (modulo) gives you whatever's left over that doesn't make a full minute.
Worked example
Here's the same Song struct and method used on a two-song playlist:
package main
import "fmt"
type Song struct {
Title string
Seconds int
}
func (s Song) Format() string {
minutes := s.Seconds / 60
seconds := s.Seconds % 60
return fmt.Sprintf("%d:%02d", minutes, seconds)
}
func main() {
playlist := []Song{
{"Rainy Day", 125},
{"Night Drive", 305},
}
totalSeconds := 0
fmt.Println("Playlist:")
for i := 0; i < len(playlist); i++ {
song := playlist[i]
fmt.Printf("%s - %s\n", song.Title, song.Format())
totalSeconds = totalSeconds + song.Seconds
}
fmt.Printf("Total runtime: %d:%02d\n", totalSeconds/60, totalSeconds%60)
}Playlist:
Rainy Day - 2:05
Night Drive - 5:05
Total runtime: 7:10Each song's Format() call turns its raw second count into a clean minutes:seconds string, and the loop keeps a running total across all of them.
Your turn
The starter program's Format method computes minutes correctly but reuses the wrong operator for seconds, and the loop in main is meant to build up a running total but shrinks it instead. Fix both marked lines.
If something goes wrong
If every song's seconds display matches its minutes (like "3:3" instead of "3:35"), you're still dividing twice instead of using % for the second value. If the total runtime prints as a negative-looking or oddly small time, check that the accumulator line adds each song's seconds rather than subtracting them. With this playlist's three songs (215, 187, and 260 seconds), the total is 662 seconds — 11 whole minutes and 2 leftover seconds — so a total that doesn't match that means one of the two fixes is still missing.
Write your code
Runs in your browser. Press Run (or Ctrl/Cmd+Enter) and the output is checked for you.
Press Esc then Tab to move keyboard focus out of the code editor.
Output will appear here after you run your code.The runtime is starting in the background. You can type now — it will be ready before you are.
The answer appears here once you have run your code at least once.
Things that often go wrong here
- Using / twice when one calculation needs the remainder instead.
- % (modulo) gives you what's left over after dividing, which is exactly what's needed for the seconds portion of a minutes:seconds display — / alone only gives whole minutes.
- Subtracting inside an accumulator loop instead of adding.
- A running total that's supposed to build up across a loop needs +=, or the equivalent total = total + x — using - drains the total instead of growing it.
- Defining a method with a name that doesn't match how it's called.
- func (s Song) Format() string must be called as song.Format() on a Song value; mismatching the receiver type or method name is a compile error.
- Forgetting %02d pads single-digit numbers with a leading zero.
- Without the 0 flag, 5 seconds would print as "3:5" instead of the conventional "3:05".
Want a blank editor instead? Open the Go playground.