Looping in Go Programming




Welcome to part 12 of the Go programming tutorial series, where we're going to cover looping/iterating in Go. Leading up to this, we've been working on a project that aggregates news. We're at the point where we have a list of sitemaps that we want to iterate over in order to visit.

In the Go language, there is only the "for" loop, there is no "while" statement, but we can still mimic what we might traditionally put in a while loop. To begin, let's show a basic for loop:

	for i:=0; i<10; i++{
		fmt.Println(i)
	}

Let's unpack what's going on here. for begins the loop, i:=0 initializes the value of i to 0, then i<10 is the check for loop to end, and then i++ simply increments i by one each loop.

Full code:

package main

import "fmt"

func main() {
	for i:=0; i<10; i++{
		fmt.Println(i)
	}
}

In order for a for loop to make sense, you likely need a starting value, but you might not need to set the value in the for loop. For example, you could have i defined before the loop, and then the incrementing could be done within the for loop:

package main

import "fmt"

func main() {
	i:=0
	for i<10{
		fmt.Println(i)
		i++
	}
}

Often, we actually want to just do something while something is the case. To start, a common use of a basic while loop is to do an infinite loop, something that just goes on forever. This is easy enough:

package main

import "fmt"

func main() {
	for {
		fmt.Println("Do stuff.")
	}
}

That would just run forever. Another common use for a while loop is to do something while something is the case. We can still do this with a for loop and a break statement. The idea of a break statement is to get out of a loop, and then we can use conditional statements to check.

package main

import "fmt"

func main() {
	x := 5
	for {
		fmt.Println("Do stuff.",x)
		x+=3
		if x > 25 {
			break
		}
	}
}

Here, we start with pre-defining x as 5, then we start an infinite loop, which just prints "Do stuff" and the current value of x. Then, in every loop, we increment x by 3. Finally, we use an if statement to check if x is greater than 25. If it is, then we break out of the loop. In this simple example, we're using x to iterate in the loop and the value of x to break the loop, but then this is very similar to

package main

import "fmt"

func main() {
	for x:=5; x<25; x+=3{
		fmt.Println("Do stuff",x)
	}
}

...but you don't need the check to be against the value of x. For example, we could do something like:

package main

import "fmt"

func main() {
	a := 3
	for x:=5; a <25; x+=3{
		fmt.Println("Do stuff",x)
		a+=4
	}
}

In this case, a starts as 3, x starts as 5. If a is greater than 25, it the loop will break, otherwise add 3 to x. Within the loop, we also increment a by 4 every time, which is what will eventually break the loop.

There's certainly more we could cover on loops and definitely on conditionals, but I think we've satisfied enough about for loops for us to go ahead and loop through our list of sitemaps, so let's get back to that.

If you recall, our code up to this point is:

package main

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
)

type Sitemapindex struct {
	Locations []Location `xml:"sitemap"`
}

type Location struct {
	Loc string `xml:"loc"`
}

func (l Location) String() string {
	return fmt.Sprintf(l.Loc)
}

func main() {
	resp, _ := http.Get("https://www.washingtonpost.com/news-sitemap-index.xml")
	bytes, _ := ioutil.ReadAll(resp.Body)
	var s Sitemapindex
	xml.Unmarshal(bytes, &s)
	fmt.Println(s.Locations)
}

At this point, s.Locations is something we'd like to iterate over. Previously we looped really more by using a "while" sort of loop in every instance, where we looped while something was or wasn't the case. In our case here, we want to loop over this list of URLs in a more traditional sense. We can do this by using Go's range. We use range to iterate over elements in data structures. We can do this with our code by doing:

	for _, Location := range s.Locations {
		fmt.Printf("%s\n", Location)
	}

The first value returned will be the index of the value, which we're designating to _, since we aren't going to be using index for any reason. If we don't use the underscore here, and instead use a variable name like index or something, Go will throw an error because we're not using the variable we defined. The next value from range will be the actual value from the data structure. We'll then just print it out for now. All together now:

package main

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
)

type Sitemapindex struct {
	Locations []Location `xml:"sitemap"`
}

type Location struct {
	Loc string `xml:"loc"`
}

func (l Location) String() string {
	return fmt.Sprintf(l.Loc)
}

func main() {
	resp, _ := http.Get("https://www.washingtonpost.com/news-sitemap-index.xml")
	bytes, _ := ioutil.ReadAll(resp.Body)

	var s Sitemapindex
	xml.Unmarshal(bytes, &s)
	//fmt.Println(s.Locations)

	for _, Location := range s.Locations {
		fmt.Printf("%s\n", Location)
	}
}

Running this, you should now clearly get output of each url on a new line as we iterate over this list. Of course, our goal now is to visit these sitemaps, and actually grab article data, so that's what we'll do in the next tutorial!

The next tutorial:





  • Introduction to the Go Programming Language
  • Go Language Syntax
  • Go Language Types
  • Pointers in Go Programming
  • Simple Web App in Go Programming
  • Structs in the Go Programming Language
  • Methods in Go Programming
  • Pointer Receivers in Go Programming
  • More Web Dev in Go Language
  • Acessing the Internet in Go
  • Parsing XML with Go Programming
  • Looping in Go Programming
  • Continuing our Go Web application
  • Mapping in Golang
  • Mapping Golang sitemap data
  • Golang Web App HTML Templating
  • Applying templating to our Golang web app
  • Goroutines - Concurrency in Goprogramming
  • Synchronizing Goroutines - Concurrency in Golang
  • Defer - Golang
  • Panic and Recover in Go Programming
  • Go Channels - Concurrency in Go
  • Go Channels buffering, iteration, and synchronization
  • Adding Concurrency to speed up our Golang Web Application