Slide 1

Slide 1 text

Developing Web Apps with Go Chang  Sau  Sheong   Sep  2014

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

What are 
 Web applications?

Slide 4

Slide 4 text

How does web applications work?

Slide 5

Slide 5 text

Browser/Client Server

Slide 6

Slide 6 text

Browser/Client Server HTTP  Request

Slide 7

Slide 7 text

Browser/Client Server HTTP  Request • Request  line GET /some/index.html HTTP/1.1

Slide 8

Slide 8 text

Browser/Client Server HTTP  Request • Request  line GET /some/index.html HTTP/1.1 • Request  headers

Slide 9

Slide 9 text

Browser/Client Server HTTP  Request • Request  line GET /some/index.html HTTP/1.1 • Request  headers • Empty  line

Slide 10

Slide 10 text

Browser/Client Server HTTP  Request • Request  line GET /some/index.html HTTP/1.1 • Request  headers • Empty  line • Message  body  (optional)

Slide 11

Slide 11 text

Browser/Client Server HTTP  Request HTTP  Response • Request  line GET /some/index.html HTTP/1.1 • Request  headers • Empty  line • Message  body  (optional)

Slide 12

Slide 12 text

Browser/Client Server HTTP  Request HTTP  Response • Request  line GET /some/index.html HTTP/1.1 • Request  headers • Empty  line • Message  body  (optional) • Status  line HTTP/1.1 200 OK

Slide 13

Slide 13 text

Browser/Client Server HTTP  Request HTTP  Response • Request  line GET /some/index.html HTTP/1.1 • Request  headers • Empty  line • Message  body  (optional) • Status  line HTTP/1.1 200 OK • Response  headers

Slide 14

Slide 14 text

Browser/Client Server HTTP  Request HTTP  Response • Request  line GET /some/index.html HTTP/1.1 • Request  headers • Empty  line • Message  body  (optional) • Status  line HTTP/1.1 200 OK • Response  headers • Empty  line

Slide 15

Slide 15 text

Browser/Client Server HTTP  Request HTTP  Response • Request  line GET /some/index.html HTTP/1.1 • Request  headers • Empty  line • Message  body  (optional) • Status  line HTTP/1.1 200 OK • Response  headers • Empty  line • Message  body  (optional)

Slide 16

Slide 16 text

Server

Slide 17

Slide 17 text

Server HTTP  Request

Slide 18

Slide 18 text

Server HTTP  Request 1.Process  request

Slide 19

Slide 19 text

Server HTTP  Request 1.Process  request 2.Execute  application   logic

Slide 20

Slide 20 text

Server HTTP  Request 1.Process  request 2.Execute  application   logic 3.Generate  response

Slide 21

Slide 21 text

Server HTTP  Request HTTP  Response 1.Process  request 2.Execute  application   logic 3.Generate  response

Slide 22

Slide 22 text

Parts of a web app • Routes
 Processing  the  request   • Templates
 Generating  response   • Store
 Persisting  data

Slide 23

Slide 23 text

What does Go have?

Slide 24

Slide 24 text

net/http

Slide 25

Slide 25 text

net/http 10

Slide 26

Slide 26 text

net/http • Server  -­‐  ServeMux(type),  Handler(type),   Handle(func),  HandleFunc(func),   ListenAndServe(func),  Serve(func) 10

Slide 27

Slide 27 text

net/http • Server  -­‐  ServeMux(type),  Handler(type),   Handle(func),  HandleFunc(func),   ListenAndServe(func),  Serve(func) • Client  -­‐  Get,  Post,  Head  etc  (func) 10

Slide 28

Slide 28 text

net/http • Server  -­‐  ServeMux(type),  Handler(type),   Handle(func),  HandleFunc(func),   ListenAndServe(func),  Serve(func) • Client  -­‐  Get,  Post,  Head  etc  (func) • Request,  Response,  ResponseWriter  (type) 10

Slide 29

Slide 29 text

net/http • Server  -­‐  ServeMux(type),  Handler(type),   Handle(func),  HandleFunc(func),   ListenAndServe(func),  Serve(func) • Client  -­‐  Get,  Post,  Head  etc  (func) • Request,  Response,  ResponseWriter  (type) • Cookie(type) 10

Slide 30

Slide 30 text

net/http • Server  -­‐  ServeMux(type),  Handler(type),   Handle(func),  HandleFunc(func),   ListenAndServe(func),  Serve(func) • Client  -­‐  Get,  Post,  Head  etc  (func) • Request,  Response,  ResponseWriter  (type) • Cookie(type) • Redirect(func) 10

Slide 31

Slide 31 text

html/template

Slide 32

Slide 32 text

Routes Process the request

Slide 33

Slide 33 text

Routes package main! ! import (! "fmt"! "net/http"! )! ! func handler(w http.ResponseWriter, r *http.Request) {! fmt.Fprintf(w, "Hello World, %s!", r.URL.Path[1:])! }! ! func main() {! http.HandleFunc("/", handler)! http.ListenAndServe(":8080", nil)! }!

Slide 34

Slide 34 text

Routes package main! ! import (! "fmt"! "net/http"! )! ! func main() {! mux := http.NewServeMux()! mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {! fmt.Fprintf(w, "Hello World, %s!", r.URL.Path[1:])! })! http.ListenAndServe(":8080", mux)! }!

Slide 35

Slide 35 text

Routes package main! ! import (! "fmt"! "net/http"! )! ! type MyHandler struct {}! ! func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {! fmt.Fprintf(w, "Hello World, %s!", r.URL.Path[1:])! }! ! func main() {! http.ListenAndServe(":8080", &MyHandler{})! }!

Slide 36

Slide 36 text

Routes type MyHandler struct {}! ! func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {! fmt.Fprintf(w, "Hello World, %s!", r.URL.Path[1:])! }! ! func main() {! server := &http.Server{! ! Addr: "0.0.0.0:8080",! ! Handler: &MyHandler{},! ! ReadTimeout: 10 * time.Second,! ! WriteTimeout: 600 * time.Second,! ! MaxHeaderBytes: 1 << 20,! }! server.ListenAndServe() ! }

Slide 37

Slide 37 text

Routes package main! ! import (! "fmt"! "net/http"! "github.com/julienschmidt/httprouter"! )! ! func main() {! router := httprouter.New() ! router.GET("/:name", hello) ! http.ListenAndServe(":8080", router)! }! ! func hello(w http.ResponseWriter, r *http.Request, p httprouter.Params) {! fmt.Fprintf(w, "Hello World, %s!", p.ByName("name"))! }!

Slide 38

Slide 38 text

Routes package main! ! import (! "fmt"! "net/http"! "github.com/julienschmidt/httprouter"! )! ! func main() {! router := httprouter.New() ! router.GET("/:name", hello) ! http.ListenAndServe(":8080", router)! }! ! func hello(w http.ResponseWriter, r *http.Request, p httprouter.Params) {! fmt.Fprintf(w, "Hello World, %s!", p.ByName("name"))! }! Not  part  of  standard   Go  libraries

Slide 39

Slide 39 text

Static assets? • Images   • Stylesheets  (CSS)   • Javascript   • Fonts

Slide 40

Slide 40 text

Serve Files func main() {! router := httprouter.New() ! router.ServeFiles("/images/*filepath", ! http.Dir("public/images"))! router.ServeFiles("/css/*filepath", ! http.Dir("public/css"))! router.ServeFiles(“/fonts/*filepath",! http.Dir("public/fonts"))! router.ServeFiles("/js/*filepath", ! http.Dir("public/js"))! http.ListenAndServe(":8080", router)! }! !

Slide 41

Slide 41 text

Templates Generate the response

Slide 42

Slide 42 text

Templates 21 Hello  World!  This  is   {  name  } name  =  “Sau  Sheong” Hello  World!  This  is   Sau  Sheong +

Slide 43

Slide 43 text

Templates

Slide 44

Slide 44 text

Templates • text/template  -­‐  data  driven  templates

Slide 45

Slide 45 text

Templates • text/template  -­‐  data  driven  templates • html/template  -­‐  data  driven  templates  for  HTML

Slide 46

Slide 46 text

Templates • text/template  -­‐  data  driven  templates • html/template  -­‐  data  driven  templates  for  HTML • Actions  (data  evaluations  or  control  structure)  -­‐   delimited  by  {{  and  }}

Slide 47

Slide 47 text

Templates • text/template  -­‐  data  driven  templates • html/template  -­‐  data  driven  templates  for  HTML • Actions  (data  evaluations  or  control  structure)  -­‐   delimited  by  {{  and  }} • Arguments  -­‐  values/variables  in  the  template

Slide 48

Slide 48 text

Templates • text/template  -­‐  data  driven  templates • html/template  -­‐  data  driven  templates  for  HTML • Actions  (data  evaluations  or  control  structure)  -­‐   delimited  by  {{  and  }} • Arguments  -­‐  values/variables  in  the  template • Pass  variables  to  template,  accessible  through   the  ‘dot’  {{ . }}

Slide 49

Slide 49 text

Templates • text/template  -­‐  data  driven  templates • html/template  -­‐  data  driven  templates  for  HTML • Actions  (data  evaluations  or  control  structure)  -­‐   delimited  by  {{  and  }} • Arguments  -­‐  values/variables  in  the  template • Pass  variables  to  template,  accessible  through   the  ‘dot’  {{ . }} • Can  define  variables  (start  with  $)

Slide 50

Slide 50 text

Templates

Slide 51

Slide 51 text

Templates • Pipeline  -­‐  a  chained  sequence  of  commands

Slide 52

Slide 52 text

Templates • Pipeline  -­‐  a  chained  sequence  of  commands • Function  -­‐  global  functions  (predefined)  or   custom  functions

Slide 53

Slide 53 text

Templates • Pipeline  -­‐  a  chained  sequence  of  commands • Function  -­‐  global  functions  (predefined)  or   custom  functions • Include  other  templates  with  keyword   ‘template’

Slide 54

Slide 54 text

Generating response

Slide 55

Slide 55 text

Generating response 1. Set  {{ define }}  in  the   template

Slide 56

Slide 56 text

Generating response 1. Set  {{ define }}  in  the   template 2. Allocate  the  template  (in  the  route)  using  New()

Slide 57

Slide 57 text

Generating response 1. Set  {{ define }}  in  the   template 2. Allocate  the  template  (in  the  route)  using  New() 3. Create  the  template  by  parsing  one  or  more   files  using  Parse(),  ParseFiles()  or   ParseGlob()  

Slide 58

Slide 58 text

Generating response 1. Set  {{ define }}  in  the   template 2. Allocate  the  template  (in  the  route)  using  New() 3. Create  the  template  by  parsing  one  or  more   files  using  Parse(),  ParseFiles()  or   ParseGlob()   4. Execute  the  template,  passing  the  output   writer  and  the  argument  (or  nil  if  none)

Slide 59

Slide 59 text

t1.html 25 {{ define "t1" }}! ! ! ! {{ template "header" }}! ! Hello World, {{ . }}!! ! ! ! {{ end }}!

Slide 60

Slide 60 text

header.html 26 {{ define "header" }}! ! ! Template Example! ! {{ end }}!

Slide 61

Slide 61 text

templates.go 27 package main! ! import (! "os"! "html/template"! )! ! func main() {! t := template.New("t1")! t = template.Must(t.ParseGlob("*.html")) ! t.Execute(writer, "Sau Sheong")! }!

Slide 62

Slide 62 text

templates.go 27 package main! ! import (! "os"! "html/template"! )! ! func main() {! t := template.New("t1")! t = template.Must(t.ParseGlob("*.html")) ! t.Execute(writer, "Sau Sheong")! }! Allocate

Slide 63

Slide 63 text

templates.go 27 package main! ! import (! "os"! "html/template"! )! ! func main() {! t := template.New("t1")! t = template.Must(t.ParseGlob("*.html")) ! t.Execute(writer, "Sau Sheong")! }! Create

Slide 64

Slide 64 text

templates.go 27 package main! ! import (! "os"! "html/template"! )! ! func main() {! t := template.New("t1")! t = template.Must(t.ParseGlob("*.html")) ! t.Execute(writer, "Sau Sheong")! }! Execute

Slide 65

Slide 65 text

templates.go 27 package main! ! import (! "os"! "html/template"! )! ! func main() {! t := template.New("t1")! t = template.Must(t.ParseGlob("*.html")) ! t.Execute(writer, "Sau Sheong")! }!

Slide 66

Slide 66 text

Response 28 ! ! ! ! ! Template Example! ! ! ! Hello World, Sau Sheong!! !

Slide 67

Slide 67 text

Response 28 ! ! ! ! ! Template Example! ! ! ! Hello World, Sau Sheong!! ! from  header.html

Slide 68

Slide 68 text

Response 28 ! ! ! ! ! Template Example! ! ! ! Hello World, Sau Sheong!! ! from  header.html replaces  {{  .  }}

Slide 69

Slide 69 text

templates.go 29 type Presentation struct {! Title string! Author string! }! ! func main() {! t := template.New("t2")! t = template.Must(t.ParseGlob("*.html")) ! presso := Presentation{! Title: "Write Web Applications with Go",! Author: "Chang Sau Sheong",! }! t.Execute(writer, presso)! }!

Slide 70

Slide 70 text

t2.html 30 {{ define "t2" }}! ! ! ! {{ template "header" }}! !

{{ .Title }}

!

{{ .Author}}

! ! ! ! {{ end }}!

Slide 71

Slide 71 text

Response 31 ! ! ! ! ! Template Example! ! ! !

Write Web Applications with Go

!

Chang Sau Sheong

! ! !

Slide 72

Slide 72 text

Store Persist application data

Slide 73

Slide 73 text

SQL

Slide 74

Slide 74 text

SQL • Direct  SQL  statements

Slide 75

Slide 75 text

SQL • Direct  SQL  statements • Mappers  (ORMs)

Slide 76

Slide 76 text

SQL • Direct  SQL  statements • Mappers  (ORMs) • gorp

Slide 77

Slide 77 text

SQL • Direct  SQL  statements • Mappers  (ORMs) • gorp • hood

Slide 78

Slide 78 text

SQL • Direct  SQL  statements • Mappers  (ORMs) • gorp • hood • beego  orm

Slide 79

Slide 79 text

SQL • Direct  SQL  statements • Mappers  (ORMs) • gorp • hood • beego  orm • gorm

Slide 80

Slide 80 text

database/sql

Slide 81

Slide 81 text

35 package main! ! import(! "log"! "fmt" ! "database/sql"! _ "github.com/lib/pq"! )! ! func main() {! db, _ := sql.Open("postgres", "dbname=blog sslmode=disable”)! defer db.Close() ! ! rows, err := db.Query("SELECT name, email FROM users WHERE email = $1", “[email protected]”); if err != nil {! log.Fatal(err)! }! for rows.Next() {! var name, email string! if err := rows.Scan(&name, &email); err != nil {! log.Fatal(err)! }! fmt.Printf("%s - %s\n", name, email)! }! }!

Slide 82

Slide 82 text

Ok when small codebase

Slide 83

Slide 83 text

Ok when small codebase Painful otherwise

Slide 84

Slide 84 text

37 https://github.com/jinzhu/gorm

Slide 85

Slide 85 text

37 https://github.com/jinzhu/gorm This  is  NOT  part  of     standard  Go  libraries

Slide 86

Slide 86 text

Define models 38 type User struct {! Id int64! Uuid string `sql:"size:255;not null;unique"`! Email string `sql:"size:255"`! Password string `sql:"size:255"`! Name string `sql:"size:255"`! CreatedAt time.Time! }! ! type Session struct {! Id int64! Uuid string `sql:"size:255;not null;unique"`! UserId int64 ! CreatedAt time.Time! } // foreign key for User table

Slide 87

Slide 87 text

Initialize database 39 var DB gorm.DB! ! // initialize gorm! func init() {! var err error! DB, err = gorm.Open("postgres", "user=test password=test dbname=test sslmode=disable")! if err != nil {! panic(fmt.Sprintf("Got error when connect database, the error is '%v'", err))! }! migrate()! }

Slide 88

Slide 88 text

Migrate tables 40 // Create tables! func migrate() {! DB.Exec("DROP TABLE users;DROP TABLE sessions;")! DB.AutoMigrate(User{})! DB.AutoMigrate(Session{})! }

Slide 89

Slide 89 text

Create 41 user := User{Name: "Sau Sheong", ! Email: "[email protected]", ! Password: “passw0rd”,! }! DB.Save(&user) ! !

Slide 90

Slide 90 text

Query 42 var user = User{}! // Get the first record! err := DB.Where("email = ?", ! "[email protected]").First(&user).Error! if err != nil {! fmt.Println("Cannot retrieve this user:", err)! } ! ! // Get the multiple records! var users []User! err := DB.Where("email LIKE ?", ! "%@gmail.com").Find(&users).Error! if err != nil {! fmt.Println("Cannot retrieve users:", err)! }

Slide 91

Slide 91 text

Update & Delete 43 var user = User{}! // Get the first record! err := DB.Where("email = ?", ! "[email protected]").First(&user).Error! if err != nil {! fmt.Println("Cannot retrieve this user:", err)! } ! ! // Update the name! user.Name = "Batman"! DB.Save(&user)! ! // Delete the record! DB.Delete(&user)!

Slide 92

Slide 92 text

Callbacks 44 // Before creating a user, add in the uuid! func (u *User) BeforeCreate() (err error) {! ! ! u.Password = encrypt(u.Password)! ! u.Uuid = createUUID()! ! return! }

Slide 93

Slide 93 text

Associations 45 user := User{Name: "Sau Sheong", ! Email: "[email protected]", ! Password: "test",! }! DB.Save(&user) ! ! sess := Session{UserId: user.Id}! DB.Save(&sess)! ! var usr User! err := DB.Model(&sess).Related(&usr).Error! if err != nil {! fmt.Println("Cannot retrieve this user:", err)! } ! ! var session Session! err := DB.Model(&user).Related(&session).Error! if err != nil {! fmt.Println("Cannot retrieve this session:", err)! }

Slide 94

Slide 94 text

Associations 45 user := User{Name: "Sau Sheong", ! Email: "[email protected]", ! Password: "test",! }! DB.Save(&user) ! ! sess := Session{UserId: user.Id}! DB.Save(&sess)! ! var usr User! err := DB.Model(&sess).Related(&usr).Error! if err != nil {! fmt.Println("Cannot retrieve this user:", err)! } ! ! var session Session! err := DB.Model(&user).Related(&session).Error! if err != nil {! fmt.Println("Cannot retrieve this session:", err)! } Retrieve  user  given   the  session

Slide 95

Slide 95 text

Associations 45 user := User{Name: "Sau Sheong", ! Email: "[email protected]", ! Password: "test",! }! DB.Save(&user) ! ! sess := Session{UserId: user.Id}! DB.Save(&sess)! ! var usr User! err := DB.Model(&sess).Related(&usr).Error! if err != nil {! fmt.Println("Cannot retrieve this user:", err)! } ! ! var session Session! err := DB.Model(&user).Related(&session).Error! if err != nil {! fmt.Println("Cannot retrieve this session:", err)! } Retrieve  session   given  the  user

Slide 96

Slide 96 text

Associations 45 user := User{Name: "Sau Sheong", ! Email: "[email protected]", ! Password: "test",! }! DB.Save(&user) ! ! sess := Session{UserId: user.Id}! DB.Save(&sess)! ! var usr User! err := DB.Model(&sess).Related(&usr).Error! if err != nil {! fmt.Println("Cannot retrieve this user:", err)! } ! ! var session Session! err := DB.Model(&user).Related(&session).Error! if err != nil {! fmt.Println("Cannot retrieve this session:", err)! }

Slide 97

Slide 97 text

Other features

Slide 98

Slide 98 text

Other features • Query  chains

Slide 99

Slide 99 text

Other features • Query  chains • Batch  updates  and  deletes

Slide 100

Slide 100 text

Other features • Query  chains • Batch  updates  and  deletes • Soft  delete  

Slide 101

Slide 101 text

Other features • Query  chains • Batch  updates  and  deletes • Soft  delete   • Associations

Slide 102

Slide 102 text

Other features • Query  chains • Batch  updates  and  deletes • Soft  delete   • Associations • Has  One

Slide 103

Slide 103 text

Other features • Query  chains • Batch  updates  and  deletes • Soft  delete   • Associations • Has  One • Belongs  To

Slide 104

Slide 104 text

Other features • Query  chains • Batch  updates  and  deletes • Soft  delete   • Associations • Has  One • Belongs  To • Has  Many

Slide 105

Slide 105 text

Other features • Query  chains • Batch  updates  and  deletes • Soft  delete   • Associations • Has  One • Belongs  To • Has  Many • Many  to  Many

Slide 106

Slide 106 text

Other features

Slide 107

Slide 107 text

Other features • FirstOrInit,  FirstOrCreate

Slide 108

Slide 108 text

Other features • FirstOrInit,  FirstOrCreate • Order,  Limit,  Offset,  Count

Slide 109

Slide 109 text

Other features • FirstOrInit,  FirstOrCreate • Order,  Limit,  Offset,  Count • Group,  Having,  Joins

Slide 110

Slide 110 text

Other features • FirstOrInit,  FirstOrCreate • Order,  Limit,  Offset,  Count • Group,  Having,  Joins • Transactions

Slide 111

Slide 111 text

Other features • FirstOrInit,  FirstOrCreate • Order,  Limit,  Offset,  Count • Group,  Having,  Joins • Transactions • Logger

Slide 112

Slide 112 text

Frameworks • Gorilla  web  toolkit   • Martini   • Gin  Gonic   • Beego   • Revel  

Slide 113

Slide 113 text

Testing Testing Go Web Apps

Slide 114

Slide 114 text

Testing is built-in

Slide 115

Slide 115 text

**_test.go

Slide 116

Slide 116 text

func TestXXX(t *testing.T) { }

Slide 117

Slide 117 text

func TestXXX(t *testing.T) { } //  Some  test  code

Slide 118

Slide 118 text

> go build

Slide 119

Slide 119 text

> go build Compile  Go  code

Slide 120

Slide 120 text

> go build > go test Compile  Go  code

Slide 121

Slide 121 text

> go build > go test Compile  Go  code Run  tests  on  Go  code

Slide 122

Slide 122 text

testing net/http/httptest

Slide 123

Slide 123 text

testing net/http/httptest Generic  testing   library

Slide 124

Slide 124 text

testing net/http/httptest Generic  testing   library Testing  library  for   web  applications

Slide 125

Slide 125 text

Unit Testing 55 package main! ! import( ! "testing"! )! ! // Test package function that adds a new user! func TestAddUser(t *testing.T) {! addUser("Sau Sheong", "[email protected]", "password")! if val, ok := users["[email protected]"]; !ok {! t.Errorf("Cannot add user")! } else {! if val.Name != "Sau Sheong" {! t.Errorf("User name is wrong")! }! }! }

Slide 126

Slide 126 text

HTTP Testing 56 package main! ! ...! ! func TestIndex(t *testing.T) { ! router := httprouter.New()! router.GET("/", index)! writer := httptest.NewRecorder()! request, _ := http.NewRequest("GET", "/", nil) ! router.ServeHTTP(writer, request)! ! if writer.Code != 302 {! t.Errorf("Response code is %v", writer.Code)! } ! }

Slide 127

Slide 127 text

HTTP Testing 57 func TestSignUp(t *testing.T) {! router := httprouter.New()! router.POST("/signup", createUser)! writer := httptest.NewRecorder()! body := strings.NewReader("name=Sau Sheong&[email protected]&password=password")! request, _ := http.NewRequest("POST", "/signup", body)! request.Header.Add("Content-Type", "application/x-www- form-urlencoded")! router.ServeHTTP(writer, request)! ! if writer.Code != 302 {! t.Errorf("Response code is %v", writer.Code)! }! if writer.Header().Get("Location") != "/login" {! t.Errorf("Location is %v", writer.Header().Get("Location"))! }! }

Slide 128

Slide 128 text

HTTP Testing 58 func TestAuthenticate(t *testing.T) {! addUser("Sau Sheong", "[email protected]", "password")! router := httprouter.New()! router.POST("/login", authenticate) ! writer := httptest.NewRecorder()! body := strings.NewReader("[email protected]&password=pa ssword")! request, _ := http.NewRequest("POST", "/login", body)! request.Header.Add("Content-Type", "application/x-www- form-urlencoded")! router.ServeHTTP(writer, request)! ...! if !strings.HasPrefix(writer.Header().Get("Set- Cookie"), "pixelate_cookie") {! t.Errorf("Cookie not set")! }! }

Slide 129

Slide 129 text

Go on the Cloud Deploying to Google App Engine

Slide 130

Slide 130 text

Go App Engine 60

Slide 131

Slide 131 text

Go App Engine • Download  the  Go  App  Engine  SDK 60

Slide 132

Slide 132 text

Go App Engine • Download  the  Go  App  Engine  SDK • Install  Mercurial 60

Slide 133

Slide 133 text

Go App Engine • Download  the  Go  App  Engine  SDK • Install  Mercurial • Add  a  file  app.yaml  to  the  same  directory 60

Slide 134

Slide 134 text

Go App Engine • Download  the  Go  App  Engine  SDK • Install  Mercurial • Add  a  file  app.yaml  to  the  same  directory 60 application: pixelate! version: 1! runtime: go! api_version: go1! ! handlers:! - url: /.*! script: _go_app

Slide 135

Slide 135 text

Go App Engine 61

Slide 136

Slide 136 text

Go App Engine • Code  changes  required: 61

Slide 137

Slide 137 text

Go App Engine • Code  changes  required: • Change  all  package  names  from  main  to  the   application  name  (in  this  case  it  is   sausheong-pixelate) 61

Slide 138

Slide 138 text

Go App Engine • Code  changes  required: • Change  all  package  names  from  main  to  the   application  name  (in  this  case  it  is   sausheong-pixelate) • Change  the  main()  function  to  init() 61

Slide 139

Slide 139 text

Go App Engine • Code  changes  required: • Change  all  package  names  from  main  to  the   application  name  (in  this  case  it  is   sausheong-pixelate) • Change  the  main()  function  to  init() • Change  from  http.ListenAndServe()  to   http.Handle(mux) 61

Slide 140

Slide 140 text

Run locally 62

Slide 141

Slide 141 text

Run locally • Run  at  command  line: 62

Slide 142

Slide 142 text

Run locally • Run  at  command  line: 62 go_appengine/dev_appserver.py sausheong-pixelate

Slide 143

Slide 143 text

Run locally • Run  at  command  line: • Open  browser  to: 62 go_appengine/dev_appserver.py sausheong-pixelate

Slide 144

Slide 144 text

Run locally • Run  at  command  line: • Open  browser  to: 62 go_appengine/dev_appserver.py sausheong-pixelate http://localhost:8080

Slide 145

Slide 145 text

Deploy to Google App Engine 63

Slide 146

Slide 146 text

Deploy to Google App Engine • Create  app  on  Google  App  Engine 63

Slide 147

Slide 147 text

Deploy to Google App Engine • Create  app  on  Google  App  Engine • Run  at  command  line: 63 go_appengine/goapp deploy sausheong-pixelate

Slide 148

Slide 148 text

Deploy to Google App Engine • Create  app  on  Google  App  Engine • Run  at  command  line: 63 go_appengine/goapp deploy sausheong-pixelate

Slide 149

Slide 149 text

Deploy to Google App Engine • Create  app  on  Google  App  Engine • Run  at  command  line: • Open  browser  to: 63 go_appengine/goapp deploy sausheong-pixelate

Slide 150

Slide 150 text

Deploy to Google App Engine • Create  app  on  Google  App  Engine • Run  at  command  line: • Open  browser  to: 63 go_appengine/goapp deploy sausheong-pixelate http://sausheong-pixelate.appspot.com

Slide 151

Slide 151 text

My projects 64 • Pixelate
 Convert  a  JPEG  file  to  a  pixelated  version   • TodayReader
 A  faster,  simpler  Today  (newspaper)  reader   • GoAuthServ
 Simple  authentication  service   • Polyglot
 Multi-­‐language  web  framework

Slide 152

Slide 152 text

Thank you [email protected] [email protected] http://github.com/sausheong @sausheong