Building Your First Web
App in Go
Andy Watson
Ionic Security
#ATOWebGo #ATO2015
All Things Open
2015
About Me
Who: Andy Watson
What: Code Flinger
Where: Ionic Security
http://ionic.com/ @andrewwatson
I used to write PHP
Lots of PHP.
Tons.
I’m a Gopher Now
Take the Tour at golang.org
Web Apps in Go
• No need for a wrapper like Apache or Nginx
• Create a self-contained, statically compiled
binary
• Cross Compile from your laptop to your
server architecture
Simple Web App
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello, worldn")
})
fmt.Print("Listening on :8080n")
http.ListenAndServe(":8080", nil)
}
Templates
Easily render well formed HTML using data
from your application
Nest templates inside each other (partials) for
easy re-use
Simple Template Example
func handleRoot(w http.ResponseWriter, req *http.Request) {
var templateStr =
"<html><body><h1>{{.}}</h1></body></html>n"
var templ =
template.Must(template.New("qr").Parse(templateStr))
templ.Execute(w, "Hello!")
}
func main() {
http.HandleFunc("/", handleRoot)
fmt.Print("Listening on :8080n")
http.ListenAndServe(":8080", nil)
}
Simple Logic
{{if .}}
<h1><a
href="{{.}}">Something!</a>
{{else}}
<h1>None</h1>
{{end}}
Iterations
type Book struct {
Author, Title string
}
func handler(w http.ResponseWriter, r *http.Request) {
// var bookList Book[]
bookList, err := lookupBooksForSale()
templ.Execute(w, bookList)
}
Template with range Operator
<h1>Books For Sale</h1>
{{range .}}
<h3>{{.Title}} by {{.Author}} </h3>
{{else}}
<h3>Sorry.</h3>
{{end}}
Outputs
<h3>Sorry.</h3> <h3>The Thing by
Stephen King</h3>
<h3>Moby Dick by
Herman Melville</h3>
With Empty List With Data
It’s the Methods, man!
func uploadHandler(…) {
if r.Method != "POST" {
err := doPostThings()
handleErrors(err)
return
}
}
Routing
Use a routing library like httprouter or mux to
match requests to handlers
Routes defined using paths and HTTP verbs
r := httprouter.New()
r.POST(”/login", LoginHandler)
r.GET("/", HomeHandler)
MiddleWare
Gets executed with every request
Used for logging, instrumentation, error
handling and more
Negroni
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Welcome to the home page!")
})
n := negroni.Classic()
n.UseHandler(mux)
n.Run(":3000")
}
https://github.com/codegangsta/negroni
Negroni Classic
Common set of middleware
• Logging
• Recovery (from panics)
• Static Content Handling
Render
• Cleans Up boilerplate template rendering code
• Handles Errors
• Takes care of headers for HTML, JSON, XML
etc
https://github.com/unrolled/render
Context
• Stores values shared during a request
lifetime
• Useful for easily passing the full context of a
request to multiple handlers
http://www.gorillatoolkit.org/pkg/context
Sessions
Keep data between requests to maintain state
• User information
• Shopping Cart
• ETC
http://www.gorillatoolkit.org/pkg/sessions
Setting up Session Handling
var sessionstore = sessions.NewCookieStore([]byte(secret))
func init() {
sessionstore.Options = &sessions.Options{
Path: "/",
MaxAge: 3600,
HttpOnly: true,
}
}
Using Sessions
session, _ := sessionstore.Get(req, "OthrNumbr-session")
session.Values["loggedin"] = true
session.Values["cust_id"] = cust.CustomerId
session.Values["description"] = cust.Description
session.Save(req, w)
http.Redirect(w, req, "/home/", 302)
Rapid Development
• Gin wraps your process
• Recompiles and Restarts Automatically
• https://github.com/codegangsta/gin
Deploy to Production
• Cross Compile for Linux
• SCP to production
• Wrap in upstart script etc
Get up
and Go
Contain Yourself
The GoLang library Docker images make it
easy to build and run your Go app in a
container
https://hub.docker.com/_/golang/
Dockerfile
FROM golang:1.5-onbuild
Docker Commands
$ docker build -t hello-world .
$ docker run --rm -it --name fred hello-world
Google App Engine
• GAE supports Go runtime
• Automatically scales up instances
• Provides highly available datastore
• Supports Go 1.4 at this time
• Soon: Migrate GAE to Managed VMs
https://cloud.google.com/appengine/
GAE DataStore
type Greeting struct {
Author string
Content string
Date time.Time
}
Fetch from DataStore
func root(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
q := datastore.NewQuery("Greeting").
Ancestor(guestbookKey(c)).Order("-Date").Limit(10)
greetings := make([]Greeting, 0, 10)
if _, err := q.GetAll(c, &greetings); err != nil {
http.Error(w, err.Error(),500)
return
}
}
GAE Example
https://github.com/GoogleCloudPlatform/appen
gine-guestbook-go
Shows session handling, data storage,
authentication and more
Other Resources
Building Web Apps with Go – by codegangtsa
http://bit.ly/WebAppsWithGo
Google Cloud Platform - Go
http://bit.ly/GoGoogleCloud
Deployed To GAE
SMS Voting Application for CSS Dev Conf
• Takes votes via SMS (Twilio) and stores
them in GAE Datastore
• Outputs them as CSV
Deployed to GAE
OthrNumbr
• Burner Numbers for
texting with strangers
• Written in Go, Deployed
on App Engine
• Users Datastore,
memcache, Twilio, Stripe
http://othrnumbr.com/
@andrewwatson
http://about.me/andrewwatson
Thank You
Kitty wants to learn concurrency
Concurrency in Go
• In Go, concurrency is accomplished by
passing shared values around on channels
• Not by sharing memory between threads
Repeat After Me
“Do not communicate by sharing
memory; instead, share memory by
communicating.”
Concurrent Routines
Created by putting “go” in front of function calls
func Announce(message string, delay time.Duration) {
go func() {
time.Sleep(delay)
fmt.Println(message)
}() // Note the parentheses - must call the function.
}
https://golang.org/doc/effective_go.html#concurrency
Channels
Go has a built in primitive types for
communicating between goroutines
c := make(chan int) // Allocate a channel.
// Start the sort in a goroutine; when it completes, signal on the channel.
go func() {
list.Sort()
c <- 1 // Send a signal; value does not matter.
}()
doSomethingForAWhile()
<-c // Wait for sort to finish; discard sent value.
Channels
• Can be buffered or unbuffered
• Can be declared to carry any other type,
even channels!
Concurrency in Go
The essential guides:
http://bit.ly/ConcurrentGo
http://bit.ly/AdvancedGoConcurrency

How to Build Your First Web App in Go

  • 1.
    Building Your FirstWeb App in Go Andy Watson Ionic Security #ATOWebGo #ATO2015 All Things Open 2015
  • 2.
    About Me Who: AndyWatson What: Code Flinger Where: Ionic Security http://ionic.com/ @andrewwatson
  • 3.
    I used towrite PHP Lots of PHP. Tons.
  • 4.
  • 5.
    Take the Tourat golang.org
  • 6.
    Web Apps inGo • No need for a wrapper like Apache or Nginx • Create a self-contained, statically compiled binary • Cross Compile from your laptop to your server architecture
  • 7.
    Simple Web App packagemain import ( "fmt" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello, worldn") }) fmt.Print("Listening on :8080n") http.ListenAndServe(":8080", nil) }
  • 8.
    Templates Easily render wellformed HTML using data from your application Nest templates inside each other (partials) for easy re-use
  • 9.
    Simple Template Example funchandleRoot(w http.ResponseWriter, req *http.Request) { var templateStr = "<html><body><h1>{{.}}</h1></body></html>n" var templ = template.Must(template.New("qr").Parse(templateStr)) templ.Execute(w, "Hello!") } func main() { http.HandleFunc("/", handleRoot) fmt.Print("Listening on :8080n") http.ListenAndServe(":8080", nil) }
  • 10.
  • 11.
    Iterations type Book struct{ Author, Title string } func handler(w http.ResponseWriter, r *http.Request) { // var bookList Book[] bookList, err := lookupBooksForSale() templ.Execute(w, bookList) }
  • 12.
    Template with rangeOperator <h1>Books For Sale</h1> {{range .}} <h3>{{.Title}} by {{.Author}} </h3> {{else}} <h3>Sorry.</h3> {{end}}
  • 13.
    Outputs <h3>Sorry.</h3> <h3>The Thingby Stephen King</h3> <h3>Moby Dick by Herman Melville</h3> With Empty List With Data
  • 14.
    It’s the Methods,man! func uploadHandler(…) { if r.Method != "POST" { err := doPostThings() handleErrors(err) return } }
  • 15.
    Routing Use a routinglibrary like httprouter or mux to match requests to handlers Routes defined using paths and HTTP verbs r := httprouter.New() r.POST(”/login", LoginHandler) r.GET("/", HomeHandler)
  • 16.
    MiddleWare Gets executed withevery request Used for logging, instrumentation, error handling and more
  • 17.
    Negroni func main() { mux:= http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, "Welcome to the home page!") }) n := negroni.Classic() n.UseHandler(mux) n.Run(":3000") } https://github.com/codegangsta/negroni
  • 18.
    Negroni Classic Common setof middleware • Logging • Recovery (from panics) • Static Content Handling
  • 19.
    Render • Cleans Upboilerplate template rendering code • Handles Errors • Takes care of headers for HTML, JSON, XML etc https://github.com/unrolled/render
  • 20.
    Context • Stores valuesshared during a request lifetime • Useful for easily passing the full context of a request to multiple handlers http://www.gorillatoolkit.org/pkg/context
  • 21.
    Sessions Keep data betweenrequests to maintain state • User information • Shopping Cart • ETC http://www.gorillatoolkit.org/pkg/sessions
  • 22.
    Setting up SessionHandling var sessionstore = sessions.NewCookieStore([]byte(secret)) func init() { sessionstore.Options = &sessions.Options{ Path: "/", MaxAge: 3600, HttpOnly: true, } }
  • 23.
    Using Sessions session, _:= sessionstore.Get(req, "OthrNumbr-session") session.Values["loggedin"] = true session.Values["cust_id"] = cust.CustomerId session.Values["description"] = cust.Description session.Save(req, w) http.Redirect(w, req, "/home/", 302)
  • 24.
    Rapid Development • Ginwraps your process • Recompiles and Restarts Automatically • https://github.com/codegangsta/gin
  • 25.
    Deploy to Production •Cross Compile for Linux • SCP to production • Wrap in upstart script etc
  • 26.
  • 27.
    Contain Yourself The GoLanglibrary Docker images make it easy to build and run your Go app in a container https://hub.docker.com/_/golang/
  • 28.
  • 29.
    Docker Commands $ dockerbuild -t hello-world . $ docker run --rm -it --name fred hello-world
  • 30.
    Google App Engine •GAE supports Go runtime • Automatically scales up instances • Provides highly available datastore • Supports Go 1.4 at this time • Soon: Migrate GAE to Managed VMs https://cloud.google.com/appengine/
  • 31.
    GAE DataStore type Greetingstruct { Author string Content string Date time.Time }
  • 32.
    Fetch from DataStore funcroot(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) q := datastore.NewQuery("Greeting"). Ancestor(guestbookKey(c)).Order("-Date").Limit(10) greetings := make([]Greeting, 0, 10) if _, err := q.GetAll(c, &greetings); err != nil { http.Error(w, err.Error(),500) return } }
  • 33.
  • 34.
    Other Resources Building WebApps with Go – by codegangtsa http://bit.ly/WebAppsWithGo Google Cloud Platform - Go http://bit.ly/GoGoogleCloud
  • 35.
    Deployed To GAE SMSVoting Application for CSS Dev Conf • Takes votes via SMS (Twilio) and stores them in GAE Datastore • Outputs them as CSV
  • 36.
    Deployed to GAE OthrNumbr •Burner Numbers for texting with strangers • Written in Go, Deployed on App Engine • Users Datastore, memcache, Twilio, Stripe http://othrnumbr.com/
  • 37.
  • 38.
    Kitty wants tolearn concurrency
  • 39.
    Concurrency in Go •In Go, concurrency is accomplished by passing shared values around on channels • Not by sharing memory between threads
  • 40.
    Repeat After Me “Donot communicate by sharing memory; instead, share memory by communicating.”
  • 41.
    Concurrent Routines Created byputting “go” in front of function calls func Announce(message string, delay time.Duration) { go func() { time.Sleep(delay) fmt.Println(message) }() // Note the parentheses - must call the function. } https://golang.org/doc/effective_go.html#concurrency
  • 42.
    Channels Go has abuilt in primitive types for communicating between goroutines c := make(chan int) // Allocate a channel. // Start the sort in a goroutine; when it completes, signal on the channel. go func() { list.Sort() c <- 1 // Send a signal; value does not matter. }() doSomethingForAWhile() <-c // Wait for sort to finish; discard sent value.
  • 43.
    Channels • Can bebuffered or unbuffered • Can be declared to carry any other type, even channels!
  • 44.
    Concurrency in Go Theessential guides: http://bit.ly/ConcurrentGo http://bit.ly/AdvancedGoConcurrency

Editor's Notes

  • #2 Hello everyone, thank you for coming. I’m Andy Watson and I’m here to talk to you about ways to use cryptography correctly in your applications
  • #3 I’m currently a senior engineer at Ionic Security which is a data protection security company based out of Atlanta, GA I’ve been a software developer professionally since 1996 when I got my first job developing large scale, distributed systems for processing streams of data collected out of particle accelerators with some Physics professors at FSU. This was “cloud” computing before it had a name. Since then I’ve built mobile, desktop and web applications for companies like The Walt Disney World Resort, Maersk Sealand, Cox Communications, CoffeeCup Software and many many others.