I am learning Go and wrote a small application that queries the Skyscanner API as my first attempt at learning. I was hoping someone more expert than me in the language could look over it at broad strokes and let me know if I'm on the right track. I really appreciate any feedback I can get!

Also, I know this is a fair amount to read over. Feedback on even one or two of the files is appreciated.

GitHub repository


package main

import (


func main() {
    params := skyscanner.Parameters{
        Adults:           1,
        Country:          "US",
        Currency:         "USD",
        Locale:           "en-US",
        OriginPlace:      "SLC-sky",
        DestinationPlace: "BNA-sky",
        OutbandDate:      "anytime",
        InboundDate:      "anytime",

    for _, v := range DestinationAirports {
        params.DestinationPlace = v
        SkyscannerQuotes := skyscanner.BrowseQuotes(params)

        w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
        quote, err := SkyscannerQuotes.LowestPrice()
        if err != nil {
            log.Printf("%v\n\n", err)
        fmt.Fprintf(w, "Price:\t$%v\nDeparture:\t%v\nReturn:\t%v\t\n\n", quote.Price, quote.DepartureDate, quote.InboundDate)


package main

// DestinationAirports is an array of all airports that should be queried
var DestinationAirports = [...]string{


package skyscanner

import (


// Config contains application secrets
type Config struct {
    MashapeKey  string `yaml:"mashape_key"`
    MashapeHost string `yaml:"mashape_host"`
    BaseURL     string `yaml:"base_url"`

func (c *Config) getConfig() *Config {
    yamlFile, err := ioutil.ReadFile("conf.yaml")
    if err != nil {
        log.Printf("yamlFile.Get err   #%v ", err)
    err = yaml.Unmarshal(yamlFile, c)
    if err != nil {
        log.Fatalf("Unmarshal: %v", err)
    return c


package skyscanner

import (

func prettyPrint(apiResponse Response) {
    fmt.Printf("%+v\n", apiResponse.Quotes)

func parseResponse(response *http.Response) Response {
    body, readErr := ioutil.ReadAll(response.Body)
    if readErr != nil {

    apiResponse := Response{}
    jsonErr := json.Unmarshal(body, &apiResponse)
    if jsonErr != nil {
    return apiResponse

func getRequest(url string) *http.Request {
    req, err := http.NewRequest(http.MethodGet, url, nil)
    var config Config
    req.Header.Set("X-Mashape-Key", config.MashapeKey)
    req.Header.Set("X-Mashape-Host", config.MashapeHost)

    if err != nil {
    return req

func getClient() *http.Client {
    return &http.Client{
        Timeout: time.Second * 2,

func formatURL(path string) string {
    var c Config
    baseURL := c.getConfig().BaseURL

    return fmt.Sprintf("%v%v", baseURL, path)

func get(url string) *http.Response {
    res, getErr := getClient().Do(getRequest(url))

    if getErr != nil {

    return res


BrowseQuotes stub
func BrowseQuotes(parameters Parameters) Response {
    browseQuotes := formatURL(fmt.Sprintf("browsequotes/v1.0/%v/%v/%v/%v/%v/%v/%v",
    res := get(browseQuotes)
    return parseResponse(res)


package skyscanner

// Parameters generic request type for skyscanner api
type Parameters struct {
    Country          string `json:"country"`
    Currency         string `json:"currency"`
    Locale           string `json:"locale"`
    OriginPlace      string `json:"originPlace"`
    DestinationPlace string `json:"destinationPlace"`
    OutbandDate      string `json:"outboundDate"`
    Adults           int    `json:"adults"`
    InboundDate      string `json:"inboundDate"`


package skyscanner

import "errors"

// Response generic response from skyscanner api
type Response struct {
    Quotes []struct {
        QuoteID     int     `json:"QuoteId"`
        MinPrice    float64 `json:"MinPrice"`
        Direct      bool    `json:"Direct"`
        OutboundLeg struct {
            CarrierIds    []int  `json:"CarrierIds"`
            OriginID      int    `json:"OriginId"`
            DestinationID int    `json:"DestinationId"`
            DepartureDate string `json:"DepartureDate"`
        } `json:"OutboundLeg"`
        InboundLeg struct {
            CarrierIds    []int  `json:"CarrierIds"`
            OriginID      int    `json:"OriginId"`
            DestinationID int    `json:"DestinationId"`
            DepartureDate string `json:"DepartureDate"`
        } `json:"InboundLeg"`
        QuoteDateTime string `json:"QuoteDateTime"`
    } `json:"Quotes"`
    Places []struct {
        PlaceID        int    `json:"PlaceId"`
        IataCode       string `json:"IataCode"`
        Name           string `json:"Name"`
        Type           string `json:"Type"`
        SkyscannerCode string `json:"SkyscannerCode"`
        CityName       string `json:"CityName"`
        CityID         string `json:"CityId"`
        CountryName    string `json:"CountryName"`
    } `json:"Places"`
    Carriers []struct {
        CarrierID int    `json:"CarrierId"`
        Name      string `json:"Name"`
    } `json:"Carriers"`
    Currencies []struct {
        Code                        string `json:"Code"`
        Symbol                      string `json:"Symbol"`
        ThousandsSeparator          string `json:"ThousandsSeparator"`
        DecimalSeparator            string `json:"DecimalSeparator"`
        SymbolOnLeft                bool   `json:"SymbolOnLeft"`
        SpaceBetweenAmountAndSymbol bool   `json:"SpaceBetweenAmountAndSymbol"`
        RoundingCoefficient         int    `json:"RoundingCoefficient"`
        DecimalDigits               int    `json:"DecimalDigits"`
    } `json:"Currencies"`

// Prices returns an array of the lowest prices for a route and date
func (r *Response) Prices() []float64 {
    priceList := make([]float64, len(r.Quotes))
    for i, v := range r.Quotes {
        priceList[i] = v.MinPrice
    return priceList

// A QuoteSummary is a summary of a outbound trip with its price and date
type QuoteSummary struct {
    Price         float64
    DepartureDate string
    InboundDate   string

// LowestPrice prints a list of the lowest prices and their accompanying dates
func (r *Response) LowestPrice() (*QuoteSummary, error) {
    quote := QuoteSummary{
    for _, v := range r.Quotes {
        if v.MinPrice < quote.Price {
            quote.Price = v.MinPrice
            quote.DepartureDate = v.OutboundLeg.DepartureDate
            quote.InboundDate = v.InboundLeg.DepartureDate
    if quote.Price == 99999999 {
        return nil, errors.New("No quote found")
    return &quote, nil


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.