Confessions of a first time speaker

This was 3rd RubyConf that I have attended so far, but this was the most special one to me. Why? Because I was one of the speakers this time.

It all started when I got a mail from the RubyConf team that my talk has been selected and they would need my confirmation that I will present the talk. Hell yeah .. I would speak at RubyConf !!! I was happy, excited, scared but never felt like accomplishing something already. All my colleagues and friends started congratulating me and I did not understood why they are doing so. I have not yet presented the talk, its just that my proposal is accepted. Big Deal. But later on I understood why they were all doing so. Although thats a story for some other time.

The day I got that email, I could not sleep that night. I was this nervous. But I always told myself that there is lot of time to prepare for it, the project I was working on was also running on 2nd gear. I use to calm myself down thinking that I could leave office a little early and would eventually find a lot of time to prepare myself for it. But things never go as you plan it, such is life. The very next week I was put on a different project and it was such a high priority project that I may also need to work on weekends to finish it on time. And I felt like things could not get worse, but I also saw it as a challenge, that If I could pull all these things off, that would be awesome. And I was up for the fight.

I had around 45 days to prepare for the talk. Now 45 days is a lot of time(yes, it is, only if you start right away). Lets face it, I did not start right away. I had so many things going on, and all needed my attention at the same time. And I learned my first very valuable lesson of life : Time Management.

Learn to manage your time efficiently. Time will not stop for you, you have to prioritize your goal. You can’t do all at the same time, learn to let go. And I did exactly that, I made my list of priorities and tried my best to stick with them. It was tough, very tough indeed. If I had to choose one thing that I would never want to miss out on, it would be fun. I simply do not want to miss out on fun. And there were times when I had to say NO to dinner with friends, NO to visit my sister and some more NO’s along the way and all these things were super fun for me. But I also realized that it was worth it.

It was exactly 20 days left when all the pieces starting fitting in and my presentation was ready. And I learned my second valuable lesson :Baby steps lead to bigger and better things. One big hurdle was crossed. It seems like the easiest of task but it takes most time to prepare the slides because you have to know your content and the flow of your talk. Once I was clear about the flow in my mind, I just had to make a plan with small achievable targets. But it will never happen that things always go as you see it, but if you stick with your plan, you will be in a better position to handle the surprising elements. Now when I did first trial of the talk at open-source Friday’s at Josh, it took me 45 minutes to finish the whole talk. But I was happy because I knew its better to have more content than fall short of content(that would have been a disaster). And more importantly I got such honest reviews from all my colleagues, all from the mistakes I am making, the pace of the talk, engaging audience more, to removing some content. Some of them even suggested me couple of jokes I could crack to lighten the environment and more importantly lighten myself :) And we all decided that I should do one more final run before we leave for Goa (the venue for RubyConf could not have been better). Although I did not do a re-run of talk because I believe that doing it again and again would make it difficult for me and would make me a little less ready to handle all the uncertain things that will happen on the stage.

It was time for the Josh team to leave for Goa. Bags were packed and we were all set to leave. It’s always a lot of fun to go to Goa when you are going to attend the conference, meet interesting people, but its not so much fun when you are suppose to give a talk and specially when its your first talk. And there was a time when everyone had slept, the lights were off and I in the middle of the night, got off the middle berth, opened my laptop and started practising the talk and I saw few people passing by laughing at me. And I learned a lesson here too: Don’t worry when the world laughs at you.

Finally we reached . The resort was beautiful, scenic and the rooms were just amazing (specially the huge TV, One of my friend got his ps3 along with him, it was so much fun to play FIFA on the huge box.).

Beautiful Resort

13406443465_99a430d9f9_b

Since we were here a day early for the conference, I had all the time in the world to relax on the beautiful private beach and did exactly that. It was Friday afternoon and so many people had already checked-in. The Josh team decided to play football on the beach in evening. It was an excellent plan. There was just one small problem with it, I should not have been a part of it in the first place. But being crazy football fan, I decided to play, and in the process I hurt myself. It felt like I may have a broken foot. Thats how much it was paining. I needed 2 guys to help me walk upto my room. And there it was, a lesson to be learnt: Think before you do.

football_on_beach

Finally, a new day and conference started. I was slotted to speak just before lunch. I was outside the conference room, at the bidder desk along with the bidder team. Finally it was 1:15 P.M, and it was my turn. I was less nervous now and was cherishing that moment (First times are always so special :) ). The talk went well. A lot of people came up to me to say that they liked the talk. It was all very overwhelming and as soon as the talk ended, the pain in my leg also disappeared.

Later in the night a beach party was organised. It was super-fun. Here is a pic from the party.

DSC03345

All in all it was an amazing conference. Awesome venue, amazing people, beach party and the bidder game-desk made this conference an unique conference. The standard has been set really high for all the conferences to follow. Kudos to organisers and volunteers for pulling this off.

(Credit to Anil Wadghule and Satish Talim for these beautiful pictures.)

Posted in Conferences, Ruby | 4 Comments

A Fun, Weather Forecast Go Web App

We shall build a fun Go app that accepts city names from a user and displays the current weather forecast in those cities, to the user.

In a previous article we learned how to use The Google Geocoding API in Go. Here too, we shall use Geocoding to help us convert addresses (like “1600 Amphitheatre Parkway, Mountain View, CA”) into geographic coordinates (like latitude 37.423021 and longitude -122.083739). Next, we shall use the weather forecast api to find out the temperature etc. at the cities entered by our user.

Register for an account at Forecast for Developers

Go to https://developer.forecast.io/register and register for an account. We shall use their free plan that allows us to use 1000 calls to their API per day. As such, there is no need to enter your credit card details. Also, this page gives you your very own API key that you will use in your program.

Study the API documentation

We need to read thro’ the API documentation of the Forecast for Developers.

Very briefly:

The Forecast Call

https://api.forecast.io/forecast/APIKEY/LATITUDE,LONGITUDE?units=ca

APIKEY should be your API key as mentioned above. LATITUDE and LONGITUDE should be the geographic coordinates of a location in decimal degrees.

The response will be a JSON-formatted object with the following properties defined:

  • latitude: The requested latitude.
  • longitude: The requested longitude.
  • timezone: The timezone name for the requested location (e.g. America/New_York).
  • offset: The current timezone offset in hours from GMT.
  • currently: A data point (see below) containing the current weather conditions at the requested location.

Data Points

A data point object represents the various weather phenomena occurring at a specific instant of time, and has many varied properties. All of these properties (except time) are optional, and will only be set if we have that type of information for that location and time.

The following JSON Schema of the API is very informative:

We shall use the above schema in our program.

Our app weather.go – first cut

Create a folder C:/go_projects/go/src/github.com/SatishTalim/weather and inside this folder write the program weather.go as follows:

package main

import (
        "encoding/json"
        "fmt"
        "io/ioutil"
        "log"
        "net/http"
        "net/url"
        "sync"
)

type DataPoint struct {
        Time                   float64
        Summary                string
        Icon                   string
        SunriseTime            float64
        SunsetTime             float64
        PrecipIntensity        float64
        PrecipIntensityMax     float64
        PrecipIntensityMaxTime float64
        PrecipProbability      float64
        PrecipType             string
        PrecipAccumulation     float64
        Temperature            float64
        TemperatureMin         float64
        TemperatureMinTime     float64
        TemperatureMax         float64
        TemperatureMaxTime     float64
        DewPoint               float64
        WindSpeed              float64
        WindBearing            float64
        CloudCover             float64
        Humidity               float64
        Pressure               float64
        Visibility             float64
        Ozone                  float64
}

type Forecast struct {
        Latitude  float64
        Longitude float64
        Timezone  string
        Offset    float64
        Currently DataPoint
        Junk      string
}

func main() {
        // Create a wait group to manage the goroutines.
        var waitGroup sync.WaitGroup

        // Perform 4 concurrent queries
        waitGroup.Add(4)
        for query := 0; query < 4; query++ {
                go Get(query, &waitGroup)
        }

        // Wait for all the queries to complete.
        waitGroup.Wait()
        fmt.Printf("All Queries Completed")
}

// Get is a function that is launched as a goroutine 
func Get(query int, waitGroup *sync.WaitGroup) {
        // Decrement the wait group count so the program knows this
        // has been completed once the goroutine exits.
        defer waitGroup.Done()

        addr := [4]string{"Pune,India", "Franklin,TN", "Sydney,Australia", "Vientiane,Lao PDR"}

        // Geocoding API
        // QueryEscape escapes the addr string so
        // it can be safely placed inside a URL query
        // safeAddr := url.QueryEscape(addr)
        safeAddr := url.QueryEscape(addr[query])
        fullUrl := fmt.Sprintf("http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=%s", safeAddr)

        // Build the request
        req, err1 := http.NewRequest("GET", fullUrl, nil)
        if err1 != nil {
                panic(err1)
        }

        // For control over HTTP client headers,
        // redirect policy, and other settings,
        // create a Client
        // A Client is an HTTP client
        client := &http.Client{}

        // Send the request via a client
        // Do sends an HTTP request and
        // returns an HTTP response
        resp, err2 := client.Do(req)
        if err2 != nil {
                panic(err2)
        }

        // Callers should close resp.Body
        // when done reading from it
        // Defer the closing of the body
        defer resp.Body.Close()

        // Read the content into a byte array
        body, dataReadErr := ioutil.ReadAll(resp.Body)
        if dataReadErr != nil {
                panic(dataReadErr)
        }

        res := make(map[string][]map[string]map[string]map[string]interface{}, 0)

        // We will be using the Unmarshal function
        // to transform our JSON bytes into the
        // appropriate structure.
        // The Unmarshal function accepts a byte array
        // and a reference to the object which shall be
        // filled with the JSON data (this is simplifying,
        // it actually accepts an interface)
        json.Unmarshal(body, &res)

        // lat, lng as float64
        lat, _ := res["results"][0]["geometry"]["location"]["lat"]
        lng, _ := res["results"][0]["geometry"]["location"]["lng"]

        // Forecast API
        // %.13f is used to convert float64 to a string
        url := fmt.Sprintf("https://api.forecast.io/forecast/yourapikey/%.13f,%.13f?units=ca", lat, lng)

        resp, err := http.Get(url)
        if err != nil {
                log.Fatal(err)
        }
        defer resp.Body.Close()
        fbody, err := ioutil.ReadAll(resp.Body)
        if err != nil {
                log.Fatal(err)
        }

        var f Forecast
        json.Unmarshal(fbody, &f)

        fmt.Println("The Weather at ", addr[query])
        fmt.Println("Timezone = ", f.Timezone)
        fmt.Println("Temp in Celsius = ", f.Currently.Temperature)
        fmt.Println("Summary = ", f.Currently.Summary)
}

Concurrent Queries

In the above program, we run queries concurrently. Let’s see how:

// Create a wait group to manage the goroutines.
var waitGroup sync.WaitGroup

The WaitGroup Example in the documentation is very informative.

A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. Then each of the goroutines runs and calls Done when finished. At the same time, Wait can be used to block until all goroutines have finished.

Run the program

In the folder C:/go_projects/go/src/github.com/SatishTalim/weather type:

$ go run weather.go

In the command window you should see something like this:

The Weather at Pune,India
Timezone = Asia/Kolkata
Temp = 26.59 Celsius
Summary = Clear

The Weather at Vientiane,Lao PDR
Timezone = Asia/Vientiane
Temp = 35.59 Celsius
Summary = Clear

The Weather at Franklin,TN
Timezone = America/Chicago
Temp = 16.10 Celsius
Summary = Clear

The Weather at Sydney,Australia
Timezone = Australia/Sydney
Temp = 24.86 Celsius
Summary = Partly Cloudy

All Queries Completed

What next?

Modify the above program, to accept multiple city addresses on a webpage. Display the result as a table on a new webpage. Deploy this app to the Google App Engine.

Here’s a sample screenshot:

weather

I have deployed this app to the Google App Engine and it is running here. You can use this code.

You can learn more about writing and deploying web apps with Go from my new book.

I hope you’ve enjoyed this post, please leave any feedback in the comments section.

Posted in Go, Tutorials | Tagged , , | 3 Comments

Do not bang your head while setting up Amazon RDS instance – like I did

Gautam Rege:

This is a tale of problems faced when migrating and existing local PostGreSQL database to Amazon RDS.

Originally posted on Deep In Rails :

While setting up Amazon RDS instance for a Ruby on Rails application, I followed simple Amazon RDS Setup Guide  , but still why I ended up banging my head for long time before success.

So I proceed by following steps, Before that I want to share my Rails application stack which is

Rails 3.2.14
Ruby 1.9.3
PostgreSQL 9.1

Step 1:  Launch DB instances

This is the simplest step and pretty straight forward

  1. Go to http://aws.amazon.com/rds and click Sign Up for Amazon RDS.
  2. Follow the on-screen instructions.

Here Point (2) is important => on-screen instruction , includes following key points

2. a) Selecting Database for a DB instance like MySQL, PostgreSQL, Oracle etc - I selected PostgreSQL

2. b) Selecting DB version, Amazon offers only PostgreSQL 9.3 as of date – as obvious I selected PostgreSQL 9.3

2. c) Selecting Instance types  from various types according to our need. – I selected db.m1.medium

2. d) Setting…

View original 1,044 more words

Posted in General | Leave a comment

Fun with Gmail and Go

Many of you at the “free” Go programming course have been asking “How do I use Gmail with Go?” To answer that question, we will quickly build a fun Go web app that uses Gmail to send off emails.

I am assuming that you have downloaded and installed Go and have set the GOPATH properly. If new to Go, then my previous article has this covered.

Sign up for a free Gmail account, if you don’t have one already.

In one of my previous articles, we learned about Golang’s package template (namely text/template and html/template). We shall use html/template here. Also, we shall use Golang’s net/smtp package to connect to Gmail.

Create the folder C:/go_projects/go/src/github.com/SatishTalim/webgmail. In this folder, create a file webgmail.go as follows:

package main

import (
        "fmt"
        "html/template"
        "net/http"
        "net/smtp"
        "os"
)

func main() {
        http.HandleFunc("/", root)
        http.HandleFunc("/mail", mail)
        fmt.Println("listening...")
        err := http.ListenAndServe(GetPort(), nil)
        if err != nil {
                panic(err)
        }
}

func GetPort() string {
        var port = os.Getenv("PORT")
        // Set a default port if there is nothing in the environment
        if port == "" {
                port = "4747"
                fmt.Println("INFO: No PORT environment variable detected, defaulting to " + port)
        }
        return ":" + port
}

func root(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, rootForm)
}

const rootForm = `
  <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Enter your mail</title>
        <link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.4.2/pure-min.css">
      </head>
      <body>
        <h2>Enter your Email</h2>
        <form action="/mail" method="post" accept-charset="utf-8" class="pure-form">
          To:<input type="text" name="to" />
          Subject<:input type="text" name="subject" />
          Message:<input type="text" name="msg" />
          <input type="submit" value="... and check the mail!"  class="pure-button pure-button-primary" />
        </form>
        <div>
          <p><b>© 2014 RubyLearning. All rights reserved.</b></p>
        </div>
      </body>
    </html>
`

const mailTemplateHTML = ` 
  <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Email Result</title>
        <link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.4.2/pure-min.css">
      </head>
      <body>
        <h2>Email Result</h2>
        <p>Your email has been sent to: </p>
        <pre>{{html .}}</pre>
        <p><a href="/">Start again!</a></p>
        <div>
          <p><b>© 2014 RubyLearning. All rights reserved.</b></p>
        </div>
      </body>
    </html>
`

var mailTemplate = template.Must(template.New("mail").Parse(mailTemplateHTML))

func mail(w http.ResponseWriter, r *http.Request) {
        to := r.FormValue("to")
        subject := r.FormValue("subject")
        message := r.FormValue("msg")

        body := "To: " + to + "\r\nSubject: " +
          subject + "\r\n\r\n" + message

        auth := smtp.PlainAuth("", "satish.talim", "password", "smtp.gmail.com")
        err := smtp.SendMail("smtp.gmail.com:587", auth, "satish.talim@gmail.com", 
          []string{to},[]byte(body))
        if err != nil {
                panic(err)
        } 

        err1 := mailTemplate.Execute(w, to)
        if err1 != nil {
                http.Error(w, err1.Error(), http.StatusInternalServerError)
        }
}

From the folder C:/go_projects/go/src/github.com/SatishTalim/webgmail you can now run the program by typing:

$ go run webgmail.go

Point your browser to http://localhost:4747 and you should see something like this in your browser:

webgmail

Note:

  • You call smtp.PlainAuth with your gmail username, password and domain name, and it returns you back an instance of smtp.Auth that you can use to send e-mails.
  • If you have setup the 2-Step Verification process in Gmail, then you need to set an application-specific password. Use this password in the above program.
  • You can send mail with smtp.SendMail.
  • SMTP on port 587 uses TLS. SSL and TLS both provide a way to encrypt a communication channel between two computers (e.g. your computer and a server). TLS is the successor to SSL and the terms SSL and TLS are used interchangeably unless you’re referring to a specific version of the protocol.

You can learn more about writing and deploying web apps with Go from my new book.

I hope you’ve enjoyed this post, please leave any feedback in the comments section.

Posted in Go, Tutorials | Tagged , , | 1 Comment

RubyConf India 2014 – The Goa Edition

The last couple of days have had a lot of discussion about The LaLiT and how their mis-management caused the organisers a lot of inconvenience. This post talks about the conference itself – what worked and what didn’t. The conference was a roaring success and attendees were not even aware about the woes the organisers had with the hotel management.

The Success Story – in numbers!

In this year’s edition we decided to include accommodation as part of the conference ticket. A very risky deal considering that we had to give a minimum room rental guarantee (120 to be precise) early on in November! This would mean we needed at least 350 participants to achieve our target. The “deal of the season” ticket price starting at Rs. 6,000 (that included stay for 2 nights with all meals, conference pass and beach party) ensured we got 404 participants!  Our gold Sponsors Josh Software, Embibe and Fab along with 4 silver sponsors, 1 Media sponsor and a whopping 10 Associate sponsors ensured that we raised the minimum 44 Lakh INR that was required.

The Venue

The location was amazing, the beach pristine and the rooms divine. We did not receive any complaints about the food either!

The Beach

The Beach

The Property

The Property

The best part of such an arrangement was that we had very very few cancellations and every other person at the hotel was a rubyist! This added to the charm of the conference as people had literally all the time in the world to meet other people and share their stories over a drink or a smoke!

The beach party was a blast and a big shout-out to the attendees to avoid the organisers nightmare – no one drowned :) or went into the water, no one was drunk and created a scene and there was no one who misbehaved. Even after we closed the bar, there were no complaints and people carried on the party on their own expense very decently!

When the organisers arrived at the hotel, we realized that the two banquet halls were quite far away with a short walk in the afternoon sun!  We improvised this and made into a Single Track event and re-scheduled the talks. Luckily, since we had the whole day (and advantage of attendees staying at the hotel) we did not have to move speakers to  the other day.

When we had a sudden electrical failure (yeah – that happened too!) we had to improvise and we had Rohit from Fab do a 7 minute standup technical comic act!

The Speakers

Full House

Full House

The talks themselves were great and applauded by all. It was a full house all the way!  Charlie started the proceeding with his talk on Concurrency in JRuby followed by various talks that included details about bundler, making faster websites, Natural language processing, SOLID principles and testing with pry. PJ Haggerty gave a talk about building the ruby community and Zachary Scott entertained the crowd with his hand-drawn slides!  Akira explained in chapters the entire Rails Hacking Guide. There were a lot of first time speakers and I was pleased to note that everyone of them gave a very professional talk. Kudos to all!

Broken Promises

As with every conference, problems did unravel and the organiser did their best to not let it affect the conference schedule or the attendees. Had the Hotel Management been a little accommodative and polite, things would have have taken a different turn after the conference and they would not have received so much flak as they have!

Water stations not refilled, lunch in the sun and threats around clearing balance amount before leaving were un-reasonbable and un-forgivable – but this had no impact on the conference.

I have been very pleased to see the support of the Ruby Community and back us up the hotels mis-behaviour. This only encourages us to do more for the conference. Thanks!

 

Posted in Conferences, Ruby | 9 Comments

Learn to build and deploy simple Go Web Apps, Part Four

In part one of this tutorial, we installed the Google App Engine SDK and then built and ran a simple web app locally. In part two, we deployed this simple web app to the Google App Engine and shared it with users worldwide. In part three, we learned about package template (namely text/template and html/template).

Now, we shall learn how to handle forms, build and deploy our Go web app GoView.

Create folders

First, create folders as shown in the diagram below:

c:go_projects
+---go
    +---src
        +---github.com
            +---SatishTalim
                +---goview
                    |   goview.go
                    |   app.yaml
                    |   favicon.ico
                    |   
                    +---images
                    |       gsv.png
                    |       
                    +---stylesheets
                            goview.css

File goview.css

Here are the contents of the file goview.css:

body {
  background-color: #C2A7F2;
  font-family: sans-serif;
}
h1 {
  color: #2A1959;
  border-bottom: 2px solid #2A1959;
}
h2 {
  color: #474B94;
  font-size: 1.2em;
}
h2, p {
  margin-left: 120px;
}

File app.yaml

Here are the contents of the file app.yaml:

application: geocodeweb

version: 1-0

runtime: go

api_version: go1

handlers:
- url: /favicon.ico
  static_files: favicon.ico
  upload: favicon.ico

# All URLs beginning with /stylesheets are treated 
# as paths to static files in the stylesheets/ directory.
- url: /stylesheets
  static_dir: stylesheets

- url: /images
  static_dir: images

- url: /.*
  script: _go_app

In part one of this series, we have already talked about the configuration file app.yaml.

Program goview.go

In the goview folder, create a file named goview.go, open it in your favorite editor, and add the following lines:

package goview

import (
    "encoding/json"
    "fmt"
        "html/template"
    "io/ioutil"
    "net/http"
    "net/url"

    "appengine"
        "appengine/urlfetch"
)

func init() {
        http.HandleFunc("/", handler)
        http.HandleFunc("/showimage", showimage)
}

func handler(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, rootForm)
}

const rootForm = `
  <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Go View</title>
        <link rel="stylesheet" href="/stylesheets/goview.css">        
      </head>
      <body>
        <h1><img style="margin-left: 120px;" src="images/gsv.png" alt="Go View" />GoView</h1>
        <h2>Accept Address</h2>
        <p>Please enter your address:</p>
        <form style="margin-left: 120px;" action="/showimage" method="post" accept-charset="utf-8">
      <input type="text" name="str" value="Type address..." id="str" />
      <input type="submit" value=".. and see the image!" />
        </form>
      </body>
    </html>
`

var upperTemplate = template.Must(template.New("showimage").Parse(upperTemplateHTML))

func showimage(w http.ResponseWriter, r *http.Request) {
        addr := r.FormValue("str")

        safeAddr := url.QueryEscape(addr)
        fullUrl := fmt.Sprintf("http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=%s", safeAddr)

        c := appengine.NewContext(r)
        client := urlfetch.Client(c)

        resp, err := client.Get(fullUrl)
        if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
        }

    defer resp.Body.Close()

        // Read the content into a byte array
    body, dataReadErr := ioutil.ReadAll(resp.Body)
    if dataReadErr != nil {
        panic(dataReadErr)
    }

        res := make(map[string][]map[string]map[string]map[string]interface{}, 0)

    json.Unmarshal(body, &res)

    lat, _ := res["results"][0]["geometry"]["location"]["lat"]
    lng, _ := res["results"][0]["geometry"]["location"]["lng"]

    // %.13f is used to convert float64 to a string
    queryUrl := fmt.Sprintf("http://maps.googleapis.com/maps/api/streetview?sensor=false&size=600x300&location=%.13f,%.13f", lat, lng)

        tempErr := upperTemplate.Execute(w, queryUrl)
        if tempErr != nil {
            http.Error(w, tempErr.Error(), http.StatusInternalServerError)
        }
}

const upperTemplateHTML = ` 
<!DOCTYPE html>
  <html>
    <head>
      <meta charset="utf-8">
      <title>Display Image</title>
      <link rel="stylesheet" href="/stylesheets/goview.css">              
    </head>
    <body>
      <h1><img style="margin-left: 120px;" src="images/gsv.png" alt="Street View" />GoView</h1>
      <h2>Image at your Address</h2>
      <img style="margin-left: 120px;" src="{{html .}}" alt="Image" />
    </body>
  </html>
`

Let us now analyze the above program.

User Form

A user form give us the ability to communicate between clients and servers. We use the form tag <form> to define a form. Go has many convenient functions to deal with a user form making it easy to integrate it in our web applications.

In the program, we have used:

<form style="margin-left: 120px;" action="/showimage" method="post" accept-charset="utf-8">
  <input type="text" name="str" value="Type address..." id="str" />
  <input type="submit" value=".. and see the image!" />
</form>

This form will submit to /showimage on the server. After the user clicks the see the image! button, the data will be sent to the showimage handler on the server.

The statement addr := r.FormValue("str") returns the value for the named component namely str of the query, which in our case is the address entered by the user.

QueryEscape

The QueryEscape function escapes the addr string so that it can be safely placed inside a URL query.

App Engine specific

For our app to work on the Google App. Engine we have modified some of our code. App Engine applications can communicate with other applications or access other resources on the web by fetching URLs. An app can use the URL Fetch service to issue HTTP and HTTPS requests and receive responses. The URL Fetch service uses Google’s network infrastructure for efficiency and scaling purposes.

defer

Callers should close resp.Body when done reading from it. Defer the closing of the body by defer resp.Body.Close()

Unmarshal

We will be using the Unmarshal function to transform our JSON bytes into the appropriate structure. The Unmarshal function accepts a byte array and a reference to the object which shall be filled with the JSON data (this is simplifying, it actually accepts an interface) – json.Unmarshal(body, &amp;res).

Here, we successfully convert an addresses (like “1600 Amphitheatre Parkway, Mountain View, CA”) into its geographic coordinates (like latitude 37.423021 and longitude -122.083739).

Using Google Geocoding and Street View Image APIs

We shall use the following apis:

to build our Go web app GoView that accepts an address as input and displays the street-view image of that address.

Open your web browser window and type the following URL:


http://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false

Based on the parameters from our HTTP request, Google responds with a lot of geographical information about the address “1600 Amphitheatre Parkway, Mountain View, CA” in the JSON format. In Google’s JSON response, you can see how the ‘<lat>’ tag, wrapped in between the ‘<location>’ tags, contains the ‘latitude’ coordinates for our given address.

Note that the base Google url we used to test out the API was:


http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=

A Street View Image request is an HTTP URL of the following form:


http://maps.googleapis.com/maps/api/streetview?parameters

The image is specified using request parameters. As is standard in URLs, all parameters are separated using the ampersand (&) character.

Required parameters

  • size specifies the output size of the image in pixels. Size is specified as {width}x{height} – for example, size=600x400 returns an image 600 pixels wide, and 400 high. Street View images can be returned in any size up to 640 by 640 pixels.
  • location can be either a text string (such as Chagrin Falls, OH) or a lat/lng value (40.457375,-80.009353). The Street View Image API will snap to the panorama photographed closest to this location. Because Street View imagery is periodically refreshed, and photographs may be taken from slightly different positions each time, it’s possible that your location may snap to a different panorama when imagery is updated.
  • sensor indicates whether or not the request came from a device using a location sensor (e.g. a GPS) to determine the location sent in this request. This value must be either true or false.

An example request is shown below.


http://maps.googleapis.com/maps/api/streetview?size=600x300&location=37.4214111,-122.0840372&sensor=false

Here is the output:

Street View Image

Deploy our app GoView

In part two you have already learned how to deploy an app to the Google App Engine. Deploy our app goview.go to the App Engine.

You can check out this app. running on the Google App. Engine here.

Almost all addresses in the USA and Europe will render a photo but I am not too sure about addresses outside of USA/Europe.

Things to do

You can download all the files used in this article from here.

As an exercise, you can modify goview.go to handle errors and also modify/optimize the goview.css file.

You can learn more about writing and deploying web apps with Go from my new book.

I hope you’ve enjoyed this post, please leave any feedback in the comments section.

You can find the other parts of the series at the following links:

Posted in Go, Tutorials | Tagged , | 5 Comments

Learn to build and deploy simple Go Web Apps, Part Three

In part one of this tutorial, we installed the Google App Engine SDK and then built and ran a simple web app locally. In part two, we deployed this simple web app to the Google App Engine and shared it with users worldwide.

Now, we will learn about the template package (namely text/template and html/template).

text/template

Usage: import "text/template"

Most server-side languages have a mechanism for taking predominantly static pages and inserting a dynamically generated component, such as a list of items. Typical examples are scripts in Java Server Pages, PHP scripting and many others. Go has adopted a relatively simple scripting language in the template package.

The package is designed to take text as input and output different text, based on transforming the original text using the values of an object.

To generate HTML output, we shall soon use package html/template, which has the same interface as this package but automatically secures HTML output against certain attacks.

The original source is called a template and will consist of text that is transmitted unchanged, and embedded commands which can act on and change text. The commands are delimited by {{ ... }}, similar to the JSP commands and PHPs.

A template is applied to a Go object. Fields from that Go object can be inserted into the template, and you can “dig” into the object to find sub-fields, etc. The current object is represented as ., so that to insert the value of the current object as a string, you use {{.}}. The package uses the fmt package by default to work out the string used as inserted values.

To insert the value of a field of the current object, you use the field name prefixed by .. For example, if the object is of type:

type Student struct {
        Name string
}

then you insert the values of Name by The name is {{.Name}}.

Thus, templates are a way to merge generic text with more specific text i.e. retain the content that is common in the template and then substitute the specific content as required.

The syntax of such definitions is to surround each template declaration with a “define” and “end” action.

The define action names the template being created by providing a string constant. Here is a simple example:

`{{define "T1"}}ONE{{end}}
{{define "T2"}}TWO{{end}}
{{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}}
{{template "T3"}}`

This defines two templates, T1 and T2, and a third T3 that invokes the other two when it is executed. Finally it invokes T3. If executed this template will produce the text

ONE TWO

In Go, we use the template package and methods like Parse, ParseFile, Execute to load a template from a string or file and then perform the merge. The content to merge is within a defined type and that has exported fields, i.e. fields within the struct that are used within the template have to start with a capital letter.

Let us look at a simple example.

Make a new folder and cd to it as follows:

$ mkdir $GOPATH/src/github.com/SatishTalim/texttmpl
$ cd $GOPATH/src/github.com/SatishTalim/texttmpl

In this folder write the program stud_struct.go as follows:

package main

import (
        "os"
        "text/template"
)

type Student struct {
        //exported field since it begins
        //with a capital letter
        Name string
}

func main() {
        //define an instance
        s := Student{"Satish"}

        //create a new template with some name
        tmpl := template.New("test")

        //parse some content and generate a template
        tmpl, err := tmpl.Parse("Hello {{.Name}}!")

        //A common use of panic is to abort if a function
        //returns an error value that we don't know how to
        //(or want to) handle.
        if err != nil {
                panic(err)
        }

        //merge template 'tmpl' with content of 's'
        err1 := tmpl.Execute(os.Stdout, s)

        if err1 != nil {
                panic(err1)
        }
}

You can now run the program by typing:

$ go run stud_struct.go

The output is:

Hello Satish!

Note:

  • New allocates a new template with the given name.
  • Parse parses a string into a template.
  • To include the content of a field within a template, enclose it within curly braces and add a dot at the beginning. E.g. if Name is a field within a struct and its value needs to be substituted while merging, then include the text {{.Name}} in the template. Do remember that the field name has to be present and it should also be exported (i.e. it should begin with a capital letter in the type definition), or there could be errors. All text outside {{.Name}} is copied to the output unchanged.
  • panic is a built-in function that stops the ordinary flow of control and begins panicking. Panics can be initiated by invoking panic directly. They can also be caused by runtime errors, such as out-of-bounds array accesses.
  • We have used the predefined variable os.Stdout which refers to the standard output to print out the merged data – os.Stdout implements io.Writer.
  • Execute applies a parsed template to the specified data object, and writes the output to os.Stdout.
  • The error type is an interface type representing an error condition, with the nil value representing no error. Go code uses error values to indicate an abnormal state.

Pipelines

A pipeline may be “chained” by separating a sequence of commands with pipeline characters '|'. In a chained pipeline, the result of each command is passed as the last argument of the following command. The output of the final command in the pipeline is the value of the pipeline.

The output of a command will be either one value or two values, the second of which has type error. If that second value is present and evaluates to non-nil, execution terminates and the error is returned to the caller of Execute.

Let us look at an example.

Make a new folder and cd to it as follows:

$ mkdir $GOPATH/src/github.com/SatishTalim/person
$ cd $GOPATH/src/github.com/SatishTalim/person

In this folder write the program person.go as follows:

package main

import (
        "os"
        "text/template"
)

type Person struct {
        Name   string
        Emails []string
}

const tmpl = `The name is {{.Name}}.
{{range .Emails}}
    His email id is {{.}}
{{end}}
`

func main() {
        person := Person{
                Name:   "Satish",
                Emails: []string{"satish@rubylearning.org", "satishtalim@gmail.com"},
        }

        t := template.New("Person template")

        t, err := t.Parse(tmpl)

        if err != nil {
                panic(err)
        }

        err = t.Execute(os.Stdout, person)

        if err != nil {
                panic(err)
        }
}

You can now run the program by typing:

$ go run person.go

The output is:

The name is Satish.

    His email id is satish@rubylearning.org

    His email id is satishtalim@gmail.com

In the above program we have {{range .Emails}}. With range the current object . is set to the successive elements of the array or slice Emails.

Variables

The template package allows you to define and use variables. In the above example, how would we print each person’s email address prefixed by their name? Let’s modify the above program.

In the code snippet:

{{range .Emails}}
    {{.}}
{{end}}

We cannot access the Name field as . is now traversing the array elements and the Name is outside of this scope. The solution is to save the value of the Name field in a variable that can be accessed anywhere in its scope. Variables in templates are prefixed by $. So we write:

{{$name := .Name}}
{{range .Emails}}
    Name is {{$name}}, email is {{.}}
{{end}}

The modified program, named new_person.go is:

package main

import (
        "os"
        "text/template"
)

type Person struct {
        Name   string
        Emails []string
}

const tmpl = `{{$name := .Name}}
{{range .Emails}}
    Name is {{$name}}, email is {{.}}
{{end}}
`

func main() {
        person := Person{
                Name:   "Satish",
                Emails: []string{"satish@rubylearning.org", "satishtalim@gmail.com"},
        }

        t := template.New("Person template")

        t, err := t.Parse(tmpl)

        if err != nil {
                panic(err)
        }

        err = t.Execute(os.Stdout, person)

        if err != nil {
                panic(err)
        }
}

You can now run the program by typing:

$ go run new_person.go

The output is:

    Name is Satish, email is satish@rubylearning.org

    Name is Satish, email is satishtalim@gmail.com

The Go template package is useful for certain kinds of text transformations involving inserting values of objects. It does not have the power of, say, regular expressions, but is faster and in many cases will be easier to use than regular expressions.

html/template

Usage: import "html/template"

Package template html/template implements data-driven templates for generating HTML output safe against code injection. It provides the same interface as package text/template and should be used instead of text/template whenever the output is HTML.

In the final part you will learn how to handle forms, build and deploy our Go web app GoView.

I hope you’ve enjoyed this post, please leave any feedback in the comments section.

You can find the other parts of the series at the following links:

Posted in Go, Tutorials | Tagged , | 5 Comments