Part 3: Learn To Build & Deploy Simple Go Web Apps

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:

|   goview.go
|   app.yaml
|   favicon.ico
|       gsv.png

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

- 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 (


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>
<meta charset="utf-8">
<title>Go View</title>
<link rel="stylesheet" href="/stylesheets/goview.css">
<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!" />

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("", safeAddr)

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

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

defer resp.Body.Close()

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

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(",%.13f", lat, lng)

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

const upperTemplateHTML = `
<!DOCTYPE html>
<meta charset="utf-8">
<title>Display Image</title>
<link rel="stylesheet" href="/stylesheets/goview.css">
<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" />

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!" />

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.


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.


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


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:,+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:

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

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.,-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:

9 thoughts on “Part 3: Learn To Build & Deploy Simple Go Web Apps

  1. I am a bit confused about how to implement / request webservices specially across different language. Reading your code I am not sure if there is any webservice being presented, althought I do see a get method and some data being uploaded/served. I am more used to having a protocol (REST, XMLRPC) datatype (encode64, JSON, XML) being exchanged. From my readings on Go it seems this can be handled from the net/http library which is used on your app, but I am still can’t seem to grasp its used as a WS. From my reading ( it seems they use other frameworks like Martini, Gorilla, GoWeb etc. So I get confused trying to learn a new framework for just one action.
    You can see how this is becoming a incremental task. Thanks or your help.

  2. Is there any way of writing log files in the same way as you would do with log.Print(“error!”) (at least in development mode)? I find it difficult to debug without even this very basic debug option.

    1. It’s being a while since this question was asked, but just for the record you can use app engine context to achieve this task.
      c := appengine.NewContext(r)
      c.Errorf(“This is a error log message: %v”, err)
      Alternatively you can use other methods of logging such as Info
      c.Infof(“This is a info log message: %v”, err)

      You can find the complete documentation for logging on AppEngine with go on the link below.

      I hope it helps,


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.