Problem overview
The function oldestPet receives a slice of pets, pets, and returns the name of the oldest one. A pet is a Pet, a struct the lesson declares for you with a Name string and an Age int. The slice has at least one pet. If several pets share the oldest age, the one that comes first in the slice wins.
For Rex (4), Bella (7) and Max (2) the answer is Bella. For Luna (3), Coco (9) and Milo (9) it is Coco, because Coco and Milo tie and Coco is earlier. A single pet, Kiki (0), is its own answer.
Approach: keep the best pet so far
This is the same running-best idea as finding a largest number, with one twist: you need the name, but you compare ages. The simplest way is to keep the whole pet. Start with the first pet as the oldest so far. Then look at every pet, and whenever one is strictly older than the current best, replace the best with it. At the end, return the best pet's name.
The tie rule is handled by the comparison. Using > means a pet of equal age never replaces the current one, so the earliest of the oldest stays. With >= the later one would win: on Luna, Coco and Milo that version returns Milo.
Step by step
- Start with
pets[0]inoldest. It is the oldest you have seen before looking at anyone else, and it makes the empty-start problem disappear. - Loop with
for _, pet := range pets. The underscore drops the index. - Compare ages with
pet.Age > oldest.Age. Fields are read with a dot. - Replace the best with
oldest = pet. Assigning a struct copies all its fields, so the name arrives together with the age. - Return
oldest.Name: the function gives back only the name, not the whole pet.
The solution in Go
func oldestPet(pets []Pet) string {
oldest := pets[0]
for _, pet := range pets {
if pet.Age > oldest.Age {
oldest = pet
}
}
return oldest.Name
}
The lesson declares the struct as type Pet struct { Name string; Age int }, so you don't write it in the editor. Go has no pair type: a small struct with named fields plays that role, and pet.Name reads better than a position number would. In your own program you can build the examples with a composite literal, such as []Pet{{"Rex", 4}, {"Bella", 7}, {"Max", 2}}.
The loop variable pet is a copy of each element, which is fine here because the function only reads it. The first pass compares pets[0] with itself, which changes nothing.
Testing
Calling oldestPet on the statement's three examples prints:
Bella
Coco
Kiki
Edge cases and common mistakes
- Using
>=. Ties then go to the last pet instead of the first. - Returning the age or the pet. The return type is
string, so the function must returnoldest.Name. - Keeping only the age. If you track just the largest age, you lose the name that goes with it. Keeping the whole pet avoids two variables that must be updated together.
- Starting from age 0. It works only because ages begin at 0 and still needs a name variable; starting from
pets[0]needs no assumption about the data.
