Now we move on to continue our discussion with control flow. Let’s start with a problem.
Problem You and your friends are getting together for a Harry Potter marathon, and you need to know how long it will take to finish them all. Using your Go skills, you already coompiled a list of all the movies. Now you can define a function to calculate the total run time.
package main
import "fmt"
var HarryPotter = []Movie{
{
Name: "Harry Potter and the Sorcerer's Stone",
Rating: "PG",
TimeInMinutes: 152,
},
{
Name: "Harry Potter and the Chamber of Secrets",
Rating: "PG",
TimeInMinutes: 161,
},
{
Name: "Harry Potter and the Prisoner of Azkaban",
Rating: "PG",
TimeInMinutes: 142,
},
{
Name: "Harry Potter and the Goblet of Fire",
Rating: "PG-13",
TimeInMinutes: 157,
},
{
Name: "Harry Potter and the Order of the Phoenix",
Rating: "PG-13",
TimeInMinutes: 129,
},
{
Name: "Harry Potter and the Half-Blood Prince",
Rating: "PG-13",
TimeInMinutes: 153,
},
{
Name: "Harry Potter and the Deathly Hallows: Part 1",
Rating: "PG-13",
TimeInMinutes: 146,
},
{
Name: "Harry Potter and the Deathly Hallows: Part 2",
Rating: "PG-13",
TimeInMinutes: 130,
},
}
func CalculateWatchTime(movies []Movie) int {
// add you code here
}
func main (){
time := CalculateWatchTime(HarryPotter)
fmt.Println("The total run time is %d minutes")
A first-time approach might have a CalculateWatchTime()
that looks like this.
func CaculateWatchTime(movies []Movie) int {
movie1time := movies[0].TimeInMinutes
movie2time := movies[1].TimeInMinutes
movie3time := movies[2].TimeInMinutes
movie4time := movies[3].TimeInMinutes
movie5time := movies[4].TimeInMinutes
movie6time := movies[5].TimeInMinutes
movie7time := movies[6].TimeInMinutes
movie8time := movies[7].TimeInMinutes
totalTime := movie1Time + movie2Time + movie3Time + movie4Time + movie5Time + movie6Time + movie7Time + movie8Time
return totalTime
}
It would almost be faster to do the math for this code by hand. The good news is we can make this a lot simpler.
We can use the for loop
function to simplifiy the above code. A for loop
is defined as: control flow statement for specifying iteration, which allows code to be executed repeatedly.wiki In simple terms, we can loop a bit of code over and over again to save us from extra typing, excessive copying and pasting, and superfluous code. It also empowers you as a programmer to do complex algorithms with just a few lines of code.
Let’s take the above problem and implement the code with a traditional c++ style for loop
. This style of for loop
traditionally takes this form:
for i := 0; i < 10; i++ {}
This code starts by defining what we call an index, which is used to keep track of what iteration of the code we are on and how many have already been run. Our index is i
and will start at 0. We see that this index is defined right after the for loop
is declared by using the keyword for
. The next part of the declaration contains the number of iterations that will take place. The line i < 10
is used to say we want this code to run 10 times. The last part defines how big our step size will be. Step size means at what interval you will count at (by 1, 2, 5, etc.). We want the code to step through every number, so our step size is 1.
Here are some code examples. For practice, try changing what the index starts, the number of iterations, and the step size.
package main
import "fmt"
func main(){
// base example
for i := 0; i < 10; i++ {
fmt.Printf("My favorite number is: %d", i)
}
// starts at 1
for i := 1; i <= 10; i++ {
fmt.Printf("My favorite number is: %d", i)
}
// change step size
for i := 0; i < 10; i = i + 2 {
fmt.Printf("My favorite number is: %d", i)
}
}
slice
sMany programming languages have a code syntax that allows you to write a for loop
that iterates over the values in a (slice)[part_1/1.3_types.md]. This is very helpful when you don’t necesarily know how long the slice is or you don’t how many iterations will need to take place.
Practice: Re-write the code from the practice example using one of the for loop
styles.
Pro-Tip
We can get a number value for the length of a slice by using the len()
expression. So if we don’t know the length of a slice when you are ready to run the program, we can use the len()
expression to handle this in the code. For example, the length of movies
can be written as len(movies)
. For the Harry Potter
example, the length should equal 8.
package main
import "fmt"
var HarryPotter = []Movie{
{
Name: "Harry Potter and the Sorcerer's Stone",
Rating: "PG",
TimeInMinutes: 152,
},
{
Name: "Harry Potter and the Chamber of Secrets",
Rating: "PG",
TimeInMinutes: 161,
},
{
Name: "Harry Potter and the Prisoner of Azkaban",
Rating: "PG",
TimeInMinutes: 142,
},
{
Name: "Harry Potter and the Goblet of Fire",
Rating: "PG-13",
TimeInMinutes: 157,
},
{
Name: "Harry Potter and the Order of the Phoenix",
Rating: "PG-13",
TimeInMinutes: 129,
},
{
Name: "Harry Potter and the Half-Blood Prince",
Rating: "PG-13",
TimeInMinutes: 153,
},
{
Name: "Harry Potter and the Deathly Hallows: Part 1",
Rating: "PG-13",
TimeInMinutes: 146,
},
{
Name: "Harry Potter and the Deathly Hallows: Part 2",
Rating: "PG-13",
TimeInMinutes: 130,
},
}
func CalculateWatchTime(movies []Movie) int {
// add you code here
}
func main (){
time := CalculateWatchTime(HarryPotter)
fmt.Println("The total run time is %d minutes")
Sometimes we want a bit of code to run until a certain boolean condition is met. This specific construct is called a while loop
. In Go, the while loop
follows the for loop
syntax. It is constructed by starting with the key word for
followed by our condition, then a set of curly braces.
for _condition {
// code here
}
Below is an example of a while loop
that you can run.
Example We want to build an app that calculates the number of days left until school is out.
package main
import (
"fmt"
"time"
)
func GetDaysLeftOfSchool(startMonth, endMonth, endDay int, isFullYear bool) int {
// the the current year
year, month, _ := time.Now().UTC().Date()
endYear := year
// check if we need to add a year to the end day
if isFullYear && startMonth >= 7 && month >= 7 {
endYear++
fmt.Println(endYear)
}
// start counter
dateTracker := time.Now().UTC()
var daysLeftOfSchool int
// this continues to run until the endDay and the endMonth match the days we are adding .to
for dateTracker.Day() != endDay || dateTracker.Month() != time.Month(endMonth) {
// add one day to dateTracker
dateTracker = dateTracker.AddDate(0, 0, 1)
// add one daty to days left
daysLeftOfSchool++
}
// return days left
return daysLeftOfSchool
}
func main(){
daysLeft := GetDaysLeftOfSchool(8, 5, 25, true)
fmt.Printf("There are %d days left of school", daysLeft)
}
NOTE: Forever Loop