May 7, 2017

Podcasts & fun with go

Got started with Go recently for a work project. It took a while to get used to the funky syntax and tabs for indentation instead of spaces. But, after a couple of weeks I can see totally a bunch of reasons why some people really love this relatively new language even if I am not yet ready to abandon my beloved python.

To speed up the process of getting up to speed with the new language, I decided to work on some very short projects that would still be a bit fun to stay motivated :-)

So, here we start with a simple RSS parser that returns a few fields of latest 5 episodes of a few podcasts that I follow. And here is a shoutout to two of my favourite podcasts:

Code

This is the minimal usable version of the program, which still manages to use a few cool little features of golang. Especially love that you can do things like parsing XML using just the standard library!

package main

import (
	"encoding/xml"
	"fmt"
	"net/http"
	"os"
)

// Channel struct shows how to directly access one level below top level XML element
type Channel struct {
	Title string `xml:"channel>title"`
	Items []Item `xml:"channel>item"`
}

// Item shows how to use a Struct from another struct
type Item struct {
	Title     string    `xml:"title"`
	Link      string    `xml:"link"`
	Enclosure Enclosure `xml:"enclosure"`
	Date      string    `xml:"pubDate"`
}

// Enclosure struct shows us how to view the attribute of an XML element
type Enclosure struct {
	Link string `xml:"url,attr"`
}

func main() {
	// golang arrays use curly braces for elements but square for identifying
	// it is an array
	urls := [...]string{
		"https://audioboom.com/channels/4070180.rss", // Dear Hank & John
		"https://audioboom.com/channels/2795952.rss", // Infinite Monkey Cage
		}

	// Using for loop to parse elements of list without using index
	for _, url := range urls {
		resp, err := http.Get(url)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		var channel Channel
		if err := xml.NewDecoder(resp.Body).Decode(&channel); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		fmt.Printf("Title: %s\n", channel.Title)
		fmt.Print("Items:\n")

		// Here we use both index and liste items in the loop
		for index, item := range channel.Items {
			fmt.Printf("[%s] %s > %s\n", item.Date, item.Title, item.Enclosure.Link)
			if index == 4 {
				break
			}
		}
	}
}

Next time I would love to add parallel fetching and parsing of RSS feeds using golang’s channels.

© Sumit Tada 2018