Go
+ App Engine
=
Johan Euphrosine
March 15, 2012
+ App Engine
=
Johan Euphrosine
March 15, 2012
Developer CommunityApp Engine allows you to scale your web application on Google Infrastructure
proppy-go-ae.appspot.com
package gopher
import (
"fmt"
"net/http"
)
// The init function is called when your application starts.
func init() {
// Register a handle for /hello URLs.
http.HandleFunc("/hello", hello)
}
// hello is an HTTP handler that prints "Hello Gopher!"
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello, Gopher!")
}
proppy-go-ae.appspot.com
application: gopher version: 1 runtime: go api_version: go1 handlers: - url: /images static_dir: images - url: /doc static_dir: doc - url: /.* script: _go_app
$ dev_appserver.py myapp/
$ appcfg.py update myapp/proppy-go-ae.appspot.com
package gopher
import (
"appengine"
"appengine/urlfetch"
"encoding/xml"
"fmt"
"net/http"
"time"
)
func init() {
// Register a handler for /hackernews URL.
http.HandleFunc("/hackernews", hackernews)
}
proppy-go-ae.appspot.com
<rss version="2.0">
<channel>
<item>
<title />
<link />
...
type HNFeed struct {
Data struct {
Items []Item `xml:"item"`
} `xml:"channel"`
}
type Item struct {
Title string `xml:"title"`
URL string `xml:"link"`
}
proppy-go-ae.appspot.com
func hackernewsItems(c appengine.Context) []Item {
client := urlfetch.Client(c)
resp, err := client.Get(HNFeedURL)
if err != nil {
c.Errorf("Error fetching %s: %s", HNFeedURL, err)
return nil
}
defer resp.Body.Close()
decoder := xml.NewDecoder(resp.Body)
var feed *HNFeed
if err = decoder.Decode(&feed); err != nil {
c.Errorf("Error decoding HNFeed: %s", err)
return nil
}
return feed.Data.Items
}
proppy-go-ae.appspot.com
func hackernews(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
w.Header().Add("Content-Type", "text/plain; charset=utf-8")
for _, item := range hackernewsItems(c) {
fmt.Fprintf(w, "%s: %s\n", item.Title, item.URL)
}
}
proppy-go-ae.appspot.com
package gopher
import (
"appengine"
"appengine/urlfetch"
"encoding/json"
"fmt"
"net/http"
"time"
)
func init() {
// Register a handler for /proggit URL.
http.HandleFunc("/proggit", proggit)
}
proppy-go-ae.appspot.com
{"data": { "children": [
{"data": { "title": ... , "url": ...}}, ...
type RedditFeed struct {
Data struct {
Items [] struct {
Data Item
} `json:"children"`
}
}
type Item struct {
Title string `xml:"title"`
URL string `xml:"link"`
}
proppy-go-ae.appspot.com
func proggitItems(c appengine.Context) []Item {
client := urlfetch.Client(c)
resp, err := client.Get(ProggitFeedURL)
if err != nil {
c.Errorf("Error fetching %s: %s", ProggitFeedURL, err)
return nil
}
defer resp.Body.Close()
decoder := json.NewDecoder(resp.Body)
var feed *RedditFeed
if err = decoder.Decode(&feed); err != nil {
c.Errorf("Error decoding RedditFeed: %s", err)
return nil
}
items := make([]Item, len(feed.Data.Items))
for i, item := range feed.Data.Items {
items[i] = item.Data
}
return items
}
proppy-go-ae.appspot.com
func proggit(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
w.Header().Add("Content-Type", "text/plain; charset=utf-8")
for _, item := range proggitItems(c) {
fmt.Fprintf(w, "%s: %s\n", item.Title, item.URL)
}
}
proppy-go-ae.appspot.com
func progginator(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
hnItems := hackernewsItems(c)
pgItems := proggitItems(c)
w.Header().Add("Content-Type", "text/plain; charset=utf-8")
for _, item := range hnItems {
fmt.Fprintf(w, "%s: %s\n", item.Title, item.URL)
}
for _, item := range pgItems {
fmt.Fprintf(w, "%s: %s\n", item.Title, item.URL)
}
}
proppy-go-ae.appspot.com
Progginator! proppy-go-ae.appspot.com
2012-03-15 04:17:59.148 hackernews: 261.695ms 2012-03-15 04:17:59.246 proggit: 97.961ms 2012-03-15 04:17:59.246 progginator: 359.822ms
func progginator_(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
results := make(chan []Item)
go func() {
results <- hackernewsItems(c)
}()
go func() {
results <- proggitItems(c)
}()
w.Header().Add("Content-Type", "text/plain; charset=utf-8")
for i := 0; i < 2; i++ {
items := <-results
for _, item := range items {
fmt.Fprintf(w, "%s: %s\n", item.Title, item.URL)
}
}
}
proppy-go-ae.appspot.com
2012-03-15 04:18:03.804 proggit: 110.451ms 2012-03-15 04:18:03.887 hackernews: 193.751ms 2012-03-15 04:18:03.887 progginator_: 193.824msproppy-go-ae.appspot.com
proppy-go-ae.appspot.com:= "developers.google.com/appengine/docs/go/"
:= "golang.org"
:= "profiles.google.com/proppy"