Code
Refactor main.go — a validated numeric field
Both ideas from this lesson go into your program — as two new menu entries. The menu loop from lesson 5 stays; we only add to it.
Give Item a PagesRead field:
type Item struct {
Title string
Pages int
PagesRead int // NEW: pages read so far
Read bool
}
Add two entries to the menu line and two cases to the switch:
fmt.Println("\n1) Show 2) Set title 3) Set pages 4) Mark read 5) Pages read 6) Progress q) Quit")
case "5":
// readInt (lesson 5) guarantees a whole number; we still check
// the BOUNDS ourselves — 0..Pages.
n := readInt("Pages read: ")
if n < 0 || n > it.Pages {
fmt.Println("Out of range (0 ..", it.Pages, ").")
continue
}
it.PagesRead = n
fmt.Println("Saved:", n, "pages.")
case "6":
fmt.Printf("Progress: %.1f%%\n", progressPercent(it))
Add the progressPercent function — with the float64 conversion before the division:
func progressPercent(it Item) float64 {
if it.Pages == 0 {
return 0
}
return float64(it.PagesRead) / float64(it.Pages) * 100
}
Finally, let formatItem show the read/total form — one changed line:
return fmt.Sprintf("%s | pages: %d/%d | %s", it.Title, it.PagesRead, it.Pages, status)
Verify — type 6, 5 + 190, 6, 1, q:
> 6
Progress: 0.0%
> 5
Pages read: 190
Saved: 190 pages.
> 6
Progress: 50.0%
> 1
The Go Programming Language | pages: 190/380 | reading
> q
Bye!
The point shows in the second 6: 50.0%, not 0% — because both sides became float64 before the division.
Tip. Change
float64(it.PagesRead) / float64(it.Pages)insideprogressPercenttoit.PagesRead / it.Pagesand run again — watch it print 0%. Breaking it on purpose is the best way to remember why the conversion matters.