SlideShare ist ein Scribd-Unternehmen logo
1 von 49
Downloaden Sie, um offline zu lesen
Go to the Cloud
Baujahr 1965


Wohnhaft in Oldenburg


Software-Entwicklung seit
mehr als 25 Jahren


Fachautor seit 1999                                                      http://www.dpunkt.de/googlego




Frank Müller                            Frank Müller - Go to the Cloud                             2

Frank Müller — Go to the Cloud — 2/49
Jobs
                                                Message Queues
                        Caching
                                                         Datenbank
    Web Server


                                                               Mail


Betriebssystem
                                                         Redundanz

                    Hardware                   Load Balancer

Typische Systeme heute
Frank Müller — Go to the Cloud — 3/49
Google App Engine
Platform as a Service


Basis für eigene Web-Anwendungen


Bereitstellung von Diensten


Transparente Skalierung


Einfaches Deployment und Monitoring

Google App Engine • Eigenschaften
Frank Müller — Go to the Cloud — 5/49
2008 Vorstellung für Python


2009 Erweiterung um Java


2011 Integration von Go


Aktuell Version 1.6.x


Go noch mit Status „experimentell“

Google App Engine • Historie
Frank Müller — Go to the Cloud — 6/49
Verarbeitung von HTTP Requests


Asynchrone Datenverarbeitung


Langlaufende Jobs


Chronologische Jobs



Google App Engine • Services für Go I
Frank Müller — Go to the Cloud — 7/49
Schemalose Datenbank


Zugriff über Schlüssel und Abfragen


Keine Relationen, dafür Schlüsseltypen


Speicher für BLOBs


Memcache


Google App Engine • Services für Go II
Frank Müller — Go to the Cloud — 8/49
Nutzung von Google-Konten möglich


Mail


Persistente Verbindungen zum Client


Skalierbare Zugriffe auf URLs



Google App Engine • Services für Go III
Frank Müller — Go to the Cloud — 9/49
Google Go
„Go hat das Ziel, die Sicherheit und 
Geschwindigkeit einer statisch 
typisierten kompilierten Sprache mit 
der Ausdrucksstärke und dem 
Komfort einer dynamisch typisierten 
interpretierten Sprache zu verbinden.
Zudem soll die Sprache für moderne, 
stark skalierende Systeme geeignet 
sein.“


— Rob Pike


Google Go • Motivation
Frank Müller — Go to the Cloud — 11/49
Ken Thompson
 ●
     Multics, Unix, B, Plan 9, ed, UTF-8
 ●
     Turing Award


Robe Pike
 ●
     Unix, Plan 9, Inferno, acme, Limbo,
     UTF-8



Google Go • Bekannte Väter
Frank Müller — Go to the Cloud — 12/49
Systemprogrammierung


Nebenläufigkeit


Statisch typisiert


Garbage Collection


Compiliert

Google Go • Kurz umrissen
Frank Müller — Go to the Cloud — 13/49
package main

 import (
   "fmt"
 )

 func greeting(greeting, name string) {
   fmt.Printf("%s, %s!n", greeting, name)
 }

 func main() {
   hello := "Hello"
   world := "World"

      greeting(hello, world)
 }



Google Go • Einfache Struktur
Frank Müller — Go to the Cloud — 14/49
Einfache Datentypen


Komplexe Datentypen


Kommunikationstypen


Funktionstypen


Interfaces und Methoden

Google Go • Flexibles Typenmodell
Frank Müller — Go to the Cloud — 15/49
type Door struct { ... }

 func NewDoor(width, height float64) *Door { ... }

 func (d *Door) Open() { ... }

 func (d *Door) Close() { ... }

 func (d Door) IsOpen() bool { ... }

 func (d Door) Size() (float64, float64) { ... }

 func (d Door) String() string { ... }




Google Go • Kein OO, aber Methoden
Frank Müller — Go to the Cloud — 16/49
type TypeStringer interface {
   TypeString() string
 }

 type Foo int64
 type Bar struct { id string }

 func (f Foo) TypeString() string {
   return "I'm a Foo (int64)."
 }

 func (b Bar) TypeString() string {
   return "I'm a Bar (struct)."
 }

 func TypePrint(ts TypeStringer) { ... }



Google Go • Polymorphie über Schnittstellen
Frank Müller — Go to the Cloud — 17/49
Goroutinen leichtgewichtiger als
Threads


Threadpools für Goroutinen


Kommunikation über typisierte
Channels


Channels nicht an Goroutinen
gebunden

Google Go • Nebenläufigkeit
Frank Müller — Go to the Cloud — 18/49
type Resource interface {
   ...
 }

 type job struct {
   jobFunc     JobFunc
   resultChan ResultChan
 }

 type JobFunc func(r Resource) *Result
 type ResultChan chan *Result

 type Result struct {
   Payload interface{}
   Error     os.Error
 }



Google Go • Einfache Nebenläufigkeit I
Frank Müller — Go to the Cloud — 19/49
type Manager struct {
   resource Resource
   jobChan chan *job
 }

 func NewManager(r Resource) *Manager {
   m := &Manager{r, make(chan *job)}

      go m.backend()

      return m
 }

 func (m *Manager) backend() {
   for j := range m.jobChan {
      j.resultChan <- j.jobFunc(m.resource)
   }
 }


Google Go • Einfache Nebenläufigkeit II
Frank Müller — Go to the Cloud — 20/49
func (m Manager) Perform(jf JobFunc) ResultChan {
   j := &job{jf, make(ResultChan)}

      go func() {
        m.jobChan <- j
      }()

      return j.resultChan
 }

 func (m Manager) Stop() {
   close(m.jobChan)
 }




Google Go • Einfache Nebenläufigkeit III
Frank Müller — Go to the Cloud — 21/49
func AnyFunc(m Manager) (*AnyResult, os.Error) {
   rc := m.Perform(func(r Resource) *Result {
      r.DoThis()
      r.DoThat()

           return &Result{..., nil}
      })

      ... // Do something else.

      result := <-rc

      if result.Error != nil {
        return nil, result.Error
      }

      return result.Payload.(*AnyResult), nil
 }


Google Go • Einfache Nebenläufigkeit IV
Frank Müller — Go to the Cloud — 22/49
Umfangreiche Standardbibliothek
 ●
     Netzwerk
 ●
     Crypto
 ●
     Zeichenketten
 ●
     Marshalling und Encoding
 ●
     I/O
 ●
     Kompression
 ●
     Bildverarbeitung
 ●
     Reflection

Google Go • Organisation in Packages
Frank Müller — Go to the Cloud — 23/49
Formatierung


Testautomatisierung


Dokumentation


Installation externer Projekte


Zentrales Projektverzeichnis

Google Go • Reichhaltige Werkzeuge
Frank Müller — Go to the Cloud — 24/49
Come Together
Come Together • Go und die App Engine
Frank Müller — Go to the Cloud — 26/49
package oop

 import (
   "fmt"
   "http"
   . "appengine"
 )

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

 func greeting(rw http.ResponseWriter, r *http.Request) {
   fmt.Fprintf(rw, "Hello, OOP 2012!")
 }




Come Together • HTTP Requests
Frank Müller — Go to the Cloud — 27/49
type Address struct {
   ...
 }

 func address(rw http.ResponseWriter, r *http.Request) {
   ctx := NewContext(r)

      r.ParseForm()

      id := r.FormValue("id")
      addr := ReadAddressById(ctx, id)

      if b, err := json.Marshal(addr); err == nil {
        rw.Header().Set("Content-Type", "application/json")
        rw.Write(b)
      }
 }


Come Together • Rückgabe von JSON
Frank Müller — Go to the Cloud — 28/49
Structs (Public / Annotation)


int(*), bool, string, float(*), []byte


Typen auf Basis dieser Typen


Eigene Typen für Zeit, *Key, BlobKey


Slices dieser Typen

Come Together • Nutzung des Datastores
Frank Müller — Go to the Cloud — 29/49
type Address struct {
   Id        string
   Street    string
   City      string
   Country string
   PhotoKey appengine.BlobKey
 }

 type Customer                struct {
   Id                         string   `datastore:"CustomerId"`
   Name                       string
   AddressKey                 *datastore.Key
   OrderKeys                  []*datastore.Key
   LastOrder                  datastore.Time
   Turnover                   Money
   AvgTurnover                Money    `datastore:"-"`
 }


Come Together • Beispielstrukturen
Frank Müller — Go to the Cloud — 30/49
func StoreCustomerAddress(ctx Context, c *Customer,
   a *Address) os.Error {
   c.AddressKey = datastore.NewKey(ctx, "Address", a.Id,
      0, nil)

      if _, err := datastore.Put(ctx, c.AddressKey, a);
        err != nil {
        return err
      }

      kc := datastore.NewKey(ctx, "Customer", c.Id, 0, nil)

      _, err := datastore.Put(ctx, kc, c)

      return err
 }



Come Together • Daten speichern
Frank Müller — Go to the Cloud — 31/49
func ReadCustomerById(ctx Context, id string)
   (*Customer, *Address, os.Error) {
   k := datastore.NewKey(ctx, "Customer", id, 0, nil)
   c := new(Customer)
   a := new(Address)

      if err := datastore.Get(ctx, k, c); err != nil {
        return nil, nil, err
      }

      if err := datastore.Get(ctx, c.AddressKey, a);
        err != nil {
        return nil, nil, err
      }

      return c, a, nil
 }


Come Together • Daten lesen
Frank Müller — Go to the Cloud — 32/49
func Book(ctx Context, fromAcc, toAcc string,
   amount Money) os.Error {
   b := func(c Context) os.Error {
      if err := subtractAmount(c, fromAcc, amount);
        err != nil {
        return err
      }

           return addAmount(c, toAcc, amount)
      }

      return datastore.RunInTransaction(ctx, b, nil)
 }




Come Together • Transaktionen
Frank Müller — Go to the Cloud — 33/49
Abfragetyp mit Filtern und Sortierung


Begrenzt auf eine Entität


Rückgabe der Daten oder Schlüssel
                                         x


Abfrage der Anzahl


Alle Daten, Limitierung oder Iterator

Come Together • Abfragemöglichkeiten
Frank Müller — Go to the Cloud — 34/49
func QueryByTurnover(ctx Context,
   turnover Money, limit int) ([]*Customer, os.Error) {
   q := datastore.NewQuery("Customer").
      Filter("Turnover >=", turnover).
      Order("-Turnover").
      Limit(limit)
   cs := make([]*Customer, 0)

      if _, err := q.GetAll(ctx, &cs); err != nil {
        return nil, err
      }

      return ts, nil
 }




Come Together • Daten abfragen
Frank Müller — Go to the Cloud — 35/49
Verteilter Puffer im Hauptspeicher


Byte Slices und serialisierte Objekte


Ablauf kann festgelegt werden


Statistik zur Analyse



Come Together • Caching
Frank Müller — Go to the Cloud — 36/49
func AllTagsCached(ctx Context) ([]*Tags, os.Error) {
   ts := make([]*Tags, 0)
   _, err := memcache.Gob.Get(ctx, "tags", &ts)

      switch err {
      case memcache.ErrCacheMiss:
        if ts, err = cacheTags(ctx); err != nil {
           return nil, err
        }

        return ts, nil
      case nil:
        return ts, nil
      }

      return nil, err
 }


Come Together • Cache lesen
Frank Müller — Go to the Cloud — 37/49
func cacheTags(ctx Context) ([]*Tags, os.Error) {
   if ts, err := ReadAllTags(ctx); err != nil {
      return nil, err
   }

      ci := &memcache.Item{
        Key:        "tags",
        Object:     ts,
        Expiration: 60,
      }

      if err = memcache.Gob.Set(ctx, ci); err != nil {
        return nil, err
      }

      return ts, nil
 }


Come Together • Cache schreiben
Frank Müller — Go to the Cloud — 38/49
HTTP Requests ohne Antwort


Längere Verarbeitung möglich


Mehrere Warteschlangen


Versionierung der Tasks



Come Together • Task Queues
Frank Müller — Go to the Cloud — 39/49
func AsyncStoreDoc(ctx Context, d *Document) os.Error {
   if b, err := json.Marshall(d); err != nil {
      return err
   }

      task := &taskqueue.Task{
        Path:     "/queues/store-doc",
        Payload: b,
        Header: make(http.Header),
      }

      task.Header.Set("Content-Type", "application/json")

      _, err = taskqueue.Add(ctx, task, "store-doc")

      return err
 }


Come Together • Task einstellen
Frank Müller — Go to the Cloud — 40/49
func storeDoc(rw http.ResponseWriter, r *http.Request) {
   var d Document

      ctx := NewContext(r)
      b, err := ioutil.ReadAll(r.Body)

      r.Body.Close()

      if err != nil {
        ctx.Errorf("Can't read request body: %v", err)
      } else if err = json.Unmarshal(b, &d); err != nil {
        ctx.Errorf("Can't unmarshal document: %v", err)
      } else if err = StoreDoc(ctx, d); err != nil {
        ctx.Errorf("Can't store document: %v", err)
      }
 }



Come Together • Task verarbeiten
Frank Müller — Go to the Cloud — 41/49
var delayedFunc = delay.Func("keyForFunc", myDelayedFunc)

 func myDelayedFunc(ctx Context, ...) {
   ...
 }

 func doSomething(rw http.ResponseWriter, r *http.Request) {
   ctx := NewContext(r)

      ...

      delayedFunc.Call(ctx, arg1, arg2, ...)
 }




Come Together • Tasks ganz einfach
Frank Müller — Go to the Cloud — 42/49
func hello(rw http.ResponseWriter, r *http.Request) {
   ctx := NewContext(r)
   u := user.Current(ctx)

      if u == nil {
        url := user.LoginURL(ctx, "/")

           fmt.Fprintf(rw, `<a href="%s">Login</a>`, url)

           return
      }

      url := user.LogoutURL(ctx, "/")

      fmt.Fprintf(rw, `<a href="%s">Logout</a>`, url)
 }



Come Together • Google Accounts nutzen
Frank Müller — Go to the Cloud — 43/49
func fetcher(rw http.ResponseWriter, r *http.Request) {
   ctx := NewContext(r)
   client := urlfetch.Client(ctx)
   resp, err := client.Get("http://...")

      if err != nil {
        http.Error(rw, err.String(),
           http.StatusInternalServerError)

           return
      }

      ...
 }




Come Together • Ressourcen via HTTP laden
Frank Müller — Go to the Cloud — 44/49
func mailer(rw http.ResponseWriter, r *http.Request) {
   ctx := NewContext(r)
   msg := &mail.Message{
      Sender: "My App <my.app@mydomain.de>",
      To:      "receiver@anydomain.de",
      Subject: "Thank you for your feedback",
      Body:    feedbackText,
   }

      if err := mail.Send(ctx, msg); err != nil {
        http.Error(rw, err.String(),
           http.StatusInternalServerError)

           return
      }
 }



Come Together • Mails senden
Frank Müller — Go to the Cloud — 45/49
Fazit
Schneller Einstieg


Einfache und leistungsfähige API


Flexible Services


Produktive Programmiersprache


Transparente Skalierung

Fazit • Vorteile
Frank Müller — Go to the Cloud — 47/49
Weniger flexibel als IaaS, Rackspace
oder Hosting


Einschränkungen in den Services und
der API


Bindung an die Plattform im Code



Fazit • Nachteile
Frank Müller — Go to the Cloud — 48/49
Fragen?

Weitere ähnliche Inhalte

Ähnlich wie Go to the Cloud

FMK 2013 Schnittstellen Datenaustausch, Longin Ziegler
FMK 2013 Schnittstellen Datenaustausch, Longin ZieglerFMK 2013 Schnittstellen Datenaustausch, Longin Ziegler
FMK 2013 Schnittstellen Datenaustausch, Longin Ziegler
Verein FM Konferenz
 

Ähnlich wie Go to the Cloud (17)

DevOpsCon - Verteilte Entwicklung in Go
DevOpsCon - Verteilte Entwicklung in GoDevOpsCon - Verteilte Entwicklung in Go
DevOpsCon - Verteilte Entwicklung in Go
 
Import Von Inhalten In Confluence (CCD'09)
Import Von Inhalten In Confluence (CCD'09)Import Von Inhalten In Confluence (CCD'09)
Import Von Inhalten In Confluence (CCD'09)
 
Skalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google GoSkalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google Go
 
JAX 2023 - Cloud Provider APIs
JAX 2023 - Cloud Provider APIsJAX 2023 - Cloud Provider APIs
JAX 2023 - Cloud Provider APIs
 
JAX 2023 - Generics in Go
JAX 2023 - Generics in GoJAX 2023 - Generics in Go
JAX 2023 - Generics in Go
 
SQL CLR Integration
SQL CLR IntegrationSQL CLR Integration
SQL CLR Integration
 
Monitoring Workshop 2017 - Philip Griesbacher - Iapetos
Monitoring Workshop 2017 - Philip Griesbacher - IapetosMonitoring Workshop 2017 - Philip Griesbacher - Iapetos
Monitoring Workshop 2017 - Philip Griesbacher - Iapetos
 
Low Code & Prozessautomatisierung
Low Code & ProzessautomatisierungLow Code & Prozessautomatisierung
Low Code & Prozessautomatisierung
 
Forms Community Server
Forms Community ServerForms Community Server
Forms Community Server
 
SplunkLive! München - Flughafen München
SplunkLive! München - Flughafen MünchenSplunkLive! München - Flughafen München
SplunkLive! München - Flughafen München
 
FMK 2013 Schnittstellen Datenaustausch, Longin Ziegler
FMK 2013 Schnittstellen Datenaustausch, Longin ZieglerFMK 2013 Schnittstellen Datenaustausch, Longin Ziegler
FMK 2013 Schnittstellen Datenaustausch, Longin Ziegler
 
Dynamic LINQ
Dynamic LINQDynamic LINQ
Dynamic LINQ
 
FMK2022 Neue Programmiertechniken von Adam Augusting
FMK2022 Neue Programmiertechniken von Adam AugustingFMK2022 Neue Programmiertechniken von Adam Augusting
FMK2022 Neue Programmiertechniken von Adam Augusting
 
Freie Software in der (Groß-)Forschung
Freie Software in der (Groß-)ForschungFreie Software in der (Groß-)Forschung
Freie Software in der (Groß-)Forschung
 
Mit Prozessautomatisierung und Co-Creation zur Digitalisierung der Öffentlich...
Mit Prozessautomatisierung und Co-Creation zur Digitalisierung der Öffentlich...Mit Prozessautomatisierung und Co-Creation zur Digitalisierung der Öffentlich...
Mit Prozessautomatisierung und Co-Creation zur Digitalisierung der Öffentlich...
 
FMK2015: FrameWork Konzepte in FileMaker Pro by Wolfgang Wunderlich
FMK2015: FrameWork Konzepte in FileMaker Pro by Wolfgang WunderlichFMK2015: FrameWork Konzepte in FileMaker Pro by Wolfgang Wunderlich
FMK2015: FrameWork Konzepte in FileMaker Pro by Wolfgang Wunderlich
 
Continuous Delivery für Cloud-native Anwendungen auf Cloud-nativer Infrastruktur
Continuous Delivery für Cloud-native Anwendungen auf Cloud-nativer InfrastrukturContinuous Delivery für Cloud-native Anwendungen auf Cloud-nativer Infrastruktur
Continuous Delivery für Cloud-native Anwendungen auf Cloud-nativer Infrastruktur
 

Mehr von Frank Müller

RESTful Web Applications with Google Go
RESTful Web Applications with Google GoRESTful Web Applications with Google Go
RESTful Web Applications with Google Go
Frank Müller
 
Pecha Kucha: Nebenläufigkeit als natürliches Paradigma
Pecha Kucha: Nebenläufigkeit als natürliches ParadigmaPecha Kucha: Nebenläufigkeit als natürliches Paradigma
Pecha Kucha: Nebenläufigkeit als natürliches Paradigma
Frank Müller
 

Mehr von Frank Müller (13)

Let The Computer Do It
Let The Computer Do ItLet The Computer Do It
Let The Computer Do It
 
Concurrency with Go
Concurrency with GoConcurrency with Go
Concurrency with Go
 
2021 OOP - Kubernetes Operatoren
2021   OOP - Kubernetes Operatoren2021   OOP - Kubernetes Operatoren
2021 OOP - Kubernetes Operatoren
 
Devs@Home - Einführung in Go
Devs@Home - Einführung in GoDevs@Home - Einführung in Go
Devs@Home - Einführung in Go
 
Fun with functions
Fun with functionsFun with functions
Fun with functions
 
Ein Gopher im Netz
Ein Gopher im NetzEin Gopher im Netz
Ein Gopher im Netz
 
Blockchains - Mehr als nur digitale Währungen
Blockchains - Mehr als nur digitale WährungenBlockchains - Mehr als nur digitale Währungen
Blockchains - Mehr als nur digitale Währungen
 
Spaß an der Nebenläufigkeit
Spaß an der NebenläufigkeitSpaß an der Nebenläufigkeit
Spaß an der Nebenläufigkeit
 
Juju - Scalable Software with Google Go
Juju - Scalable Software with Google GoJuju - Scalable Software with Google Go
Juju - Scalable Software with Google Go
 
RESTful Web Applications with Google Go
RESTful Web Applications with Google GoRESTful Web Applications with Google Go
RESTful Web Applications with Google Go
 
OOP 2013 - Weltweite Entwicklung von Open Source Software
OOP 2013 - Weltweite Entwicklung von Open Source SoftwareOOP 2013 - Weltweite Entwicklung von Open Source Software
OOP 2013 - Weltweite Entwicklung von Open Source Software
 
Pecha Kucha: Nebenläufigkeit als natürliches Paradigma
Pecha Kucha: Nebenläufigkeit als natürliches ParadigmaPecha Kucha: Nebenläufigkeit als natürliches Paradigma
Pecha Kucha: Nebenläufigkeit als natürliches Paradigma
 
Agility And The Way To SOA
Agility And The Way To SOAAgility And The Way To SOA
Agility And The Way To SOA
 

Go to the Cloud

  • 1. Go to the Cloud
  • 2. Baujahr 1965 Wohnhaft in Oldenburg Software-Entwicklung seit mehr als 25 Jahren Fachautor seit 1999 http://www.dpunkt.de/googlego Frank Müller Frank Müller - Go to the Cloud 2 Frank Müller — Go to the Cloud — 2/49
  • 3. Jobs Message Queues Caching Datenbank Web Server Mail Betriebssystem Redundanz Hardware Load Balancer Typische Systeme heute Frank Müller — Go to the Cloud — 3/49
  • 5. Platform as a Service Basis für eigene Web-Anwendungen Bereitstellung von Diensten Transparente Skalierung Einfaches Deployment und Monitoring Google App Engine • Eigenschaften Frank Müller — Go to the Cloud — 5/49
  • 6. 2008 Vorstellung für Python 2009 Erweiterung um Java 2011 Integration von Go Aktuell Version 1.6.x Go noch mit Status „experimentell“ Google App Engine • Historie Frank Müller — Go to the Cloud — 6/49
  • 7. Verarbeitung von HTTP Requests Asynchrone Datenverarbeitung Langlaufende Jobs Chronologische Jobs Google App Engine • Services für Go I Frank Müller — Go to the Cloud — 7/49
  • 8. Schemalose Datenbank Zugriff über Schlüssel und Abfragen Keine Relationen, dafür Schlüsseltypen Speicher für BLOBs Memcache Google App Engine • Services für Go II Frank Müller — Go to the Cloud — 8/49
  • 9. Nutzung von Google-Konten möglich Mail Persistente Verbindungen zum Client Skalierbare Zugriffe auf URLs Google App Engine • Services für Go III Frank Müller — Go to the Cloud — 9/49
  • 12. Ken Thompson ● Multics, Unix, B, Plan 9, ed, UTF-8 ● Turing Award Robe Pike ● Unix, Plan 9, Inferno, acme, Limbo, UTF-8 Google Go • Bekannte Väter Frank Müller — Go to the Cloud — 12/49
  • 13. Systemprogrammierung Nebenläufigkeit Statisch typisiert Garbage Collection Compiliert Google Go • Kurz umrissen Frank Müller — Go to the Cloud — 13/49
  • 14. package main import ( "fmt" ) func greeting(greeting, name string) { fmt.Printf("%s, %s!n", greeting, name) } func main() { hello := "Hello" world := "World" greeting(hello, world) } Google Go • Einfache Struktur Frank Müller — Go to the Cloud — 14/49
  • 15. Einfache Datentypen Komplexe Datentypen Kommunikationstypen Funktionstypen Interfaces und Methoden Google Go • Flexibles Typenmodell Frank Müller — Go to the Cloud — 15/49
  • 16. type Door struct { ... } func NewDoor(width, height float64) *Door { ... } func (d *Door) Open() { ... } func (d *Door) Close() { ... } func (d Door) IsOpen() bool { ... } func (d Door) Size() (float64, float64) { ... } func (d Door) String() string { ... } Google Go • Kein OO, aber Methoden Frank Müller — Go to the Cloud — 16/49
  • 17. type TypeStringer interface { TypeString() string } type Foo int64 type Bar struct { id string } func (f Foo) TypeString() string { return "I'm a Foo (int64)." } func (b Bar) TypeString() string { return "I'm a Bar (struct)." } func TypePrint(ts TypeStringer) { ... } Google Go • Polymorphie über Schnittstellen Frank Müller — Go to the Cloud — 17/49
  • 18. Goroutinen leichtgewichtiger als Threads Threadpools für Goroutinen Kommunikation über typisierte Channels Channels nicht an Goroutinen gebunden Google Go • Nebenläufigkeit Frank Müller — Go to the Cloud — 18/49
  • 19. type Resource interface { ... } type job struct { jobFunc JobFunc resultChan ResultChan } type JobFunc func(r Resource) *Result type ResultChan chan *Result type Result struct { Payload interface{} Error os.Error } Google Go • Einfache Nebenläufigkeit I Frank Müller — Go to the Cloud — 19/49
  • 20. type Manager struct { resource Resource jobChan chan *job } func NewManager(r Resource) *Manager { m := &Manager{r, make(chan *job)} go m.backend() return m } func (m *Manager) backend() { for j := range m.jobChan { j.resultChan <- j.jobFunc(m.resource) } } Google Go • Einfache Nebenläufigkeit II Frank Müller — Go to the Cloud — 20/49
  • 21. func (m Manager) Perform(jf JobFunc) ResultChan { j := &job{jf, make(ResultChan)} go func() { m.jobChan <- j }() return j.resultChan } func (m Manager) Stop() { close(m.jobChan) } Google Go • Einfache Nebenläufigkeit III Frank Müller — Go to the Cloud — 21/49
  • 22. func AnyFunc(m Manager) (*AnyResult, os.Error) { rc := m.Perform(func(r Resource) *Result { r.DoThis() r.DoThat() return &Result{..., nil} }) ... // Do something else. result := <-rc if result.Error != nil { return nil, result.Error } return result.Payload.(*AnyResult), nil } Google Go • Einfache Nebenläufigkeit IV Frank Müller — Go to the Cloud — 22/49
  • 23. Umfangreiche Standardbibliothek ● Netzwerk ● Crypto ● Zeichenketten ● Marshalling und Encoding ● I/O ● Kompression ● Bildverarbeitung ● Reflection Google Go • Organisation in Packages Frank Müller — Go to the Cloud — 23/49
  • 24. Formatierung Testautomatisierung Dokumentation Installation externer Projekte Zentrales Projektverzeichnis Google Go • Reichhaltige Werkzeuge Frank Müller — Go to the Cloud — 24/49
  • 26. Come Together • Go und die App Engine Frank Müller — Go to the Cloud — 26/49
  • 27. package oop import ( "fmt" "http" . "appengine" ) func init() { http.HandleFunc("/", greeting) } func greeting(rw http.ResponseWriter, r *http.Request) { fmt.Fprintf(rw, "Hello, OOP 2012!") } Come Together • HTTP Requests Frank Müller — Go to the Cloud — 27/49
  • 28. type Address struct { ... } func address(rw http.ResponseWriter, r *http.Request) { ctx := NewContext(r) r.ParseForm() id := r.FormValue("id") addr := ReadAddressById(ctx, id) if b, err := json.Marshal(addr); err == nil { rw.Header().Set("Content-Type", "application/json") rw.Write(b) } } Come Together • Rückgabe von JSON Frank Müller — Go to the Cloud — 28/49
  • 29. Structs (Public / Annotation) int(*), bool, string, float(*), []byte Typen auf Basis dieser Typen Eigene Typen für Zeit, *Key, BlobKey Slices dieser Typen Come Together • Nutzung des Datastores Frank Müller — Go to the Cloud — 29/49
  • 30. type Address struct { Id string Street string City string Country string PhotoKey appengine.BlobKey } type Customer struct { Id string `datastore:"CustomerId"` Name string AddressKey *datastore.Key OrderKeys []*datastore.Key LastOrder datastore.Time Turnover Money AvgTurnover Money `datastore:"-"` } Come Together • Beispielstrukturen Frank Müller — Go to the Cloud — 30/49
  • 31. func StoreCustomerAddress(ctx Context, c *Customer, a *Address) os.Error { c.AddressKey = datastore.NewKey(ctx, "Address", a.Id, 0, nil) if _, err := datastore.Put(ctx, c.AddressKey, a); err != nil { return err } kc := datastore.NewKey(ctx, "Customer", c.Id, 0, nil) _, err := datastore.Put(ctx, kc, c) return err } Come Together • Daten speichern Frank Müller — Go to the Cloud — 31/49
  • 32. func ReadCustomerById(ctx Context, id string) (*Customer, *Address, os.Error) { k := datastore.NewKey(ctx, "Customer", id, 0, nil) c := new(Customer) a := new(Address) if err := datastore.Get(ctx, k, c); err != nil { return nil, nil, err } if err := datastore.Get(ctx, c.AddressKey, a); err != nil { return nil, nil, err } return c, a, nil } Come Together • Daten lesen Frank Müller — Go to the Cloud — 32/49
  • 33. func Book(ctx Context, fromAcc, toAcc string, amount Money) os.Error { b := func(c Context) os.Error { if err := subtractAmount(c, fromAcc, amount); err != nil { return err } return addAmount(c, toAcc, amount) } return datastore.RunInTransaction(ctx, b, nil) } Come Together • Transaktionen Frank Müller — Go to the Cloud — 33/49
  • 34. Abfragetyp mit Filtern und Sortierung Begrenzt auf eine Entität Rückgabe der Daten oder Schlüssel x Abfrage der Anzahl Alle Daten, Limitierung oder Iterator Come Together • Abfragemöglichkeiten Frank Müller — Go to the Cloud — 34/49
  • 35. func QueryByTurnover(ctx Context, turnover Money, limit int) ([]*Customer, os.Error) { q := datastore.NewQuery("Customer"). Filter("Turnover >=", turnover). Order("-Turnover"). Limit(limit) cs := make([]*Customer, 0) if _, err := q.GetAll(ctx, &cs); err != nil { return nil, err } return ts, nil } Come Together • Daten abfragen Frank Müller — Go to the Cloud — 35/49
  • 36. Verteilter Puffer im Hauptspeicher Byte Slices und serialisierte Objekte Ablauf kann festgelegt werden Statistik zur Analyse Come Together • Caching Frank Müller — Go to the Cloud — 36/49
  • 37. func AllTagsCached(ctx Context) ([]*Tags, os.Error) { ts := make([]*Tags, 0) _, err := memcache.Gob.Get(ctx, "tags", &ts) switch err { case memcache.ErrCacheMiss: if ts, err = cacheTags(ctx); err != nil { return nil, err } return ts, nil case nil: return ts, nil } return nil, err } Come Together • Cache lesen Frank Müller — Go to the Cloud — 37/49
  • 38. func cacheTags(ctx Context) ([]*Tags, os.Error) { if ts, err := ReadAllTags(ctx); err != nil { return nil, err } ci := &memcache.Item{ Key: "tags", Object: ts, Expiration: 60, } if err = memcache.Gob.Set(ctx, ci); err != nil { return nil, err } return ts, nil } Come Together • Cache schreiben Frank Müller — Go to the Cloud — 38/49
  • 39. HTTP Requests ohne Antwort Längere Verarbeitung möglich Mehrere Warteschlangen Versionierung der Tasks Come Together • Task Queues Frank Müller — Go to the Cloud — 39/49
  • 40. func AsyncStoreDoc(ctx Context, d *Document) os.Error { if b, err := json.Marshall(d); err != nil { return err } task := &taskqueue.Task{ Path: "/queues/store-doc", Payload: b, Header: make(http.Header), } task.Header.Set("Content-Type", "application/json") _, err = taskqueue.Add(ctx, task, "store-doc") return err } Come Together • Task einstellen Frank Müller — Go to the Cloud — 40/49
  • 41. func storeDoc(rw http.ResponseWriter, r *http.Request) { var d Document ctx := NewContext(r) b, err := ioutil.ReadAll(r.Body) r.Body.Close() if err != nil { ctx.Errorf("Can't read request body: %v", err) } else if err = json.Unmarshal(b, &d); err != nil { ctx.Errorf("Can't unmarshal document: %v", err) } else if err = StoreDoc(ctx, d); err != nil { ctx.Errorf("Can't store document: %v", err) } } Come Together • Task verarbeiten Frank Müller — Go to the Cloud — 41/49
  • 42. var delayedFunc = delay.Func("keyForFunc", myDelayedFunc) func myDelayedFunc(ctx Context, ...) { ... } func doSomething(rw http.ResponseWriter, r *http.Request) { ctx := NewContext(r) ... delayedFunc.Call(ctx, arg1, arg2, ...) } Come Together • Tasks ganz einfach Frank Müller — Go to the Cloud — 42/49
  • 43. func hello(rw http.ResponseWriter, r *http.Request) { ctx := NewContext(r) u := user.Current(ctx) if u == nil { url := user.LoginURL(ctx, "/") fmt.Fprintf(rw, `<a href="%s">Login</a>`, url) return } url := user.LogoutURL(ctx, "/") fmt.Fprintf(rw, `<a href="%s">Logout</a>`, url) } Come Together • Google Accounts nutzen Frank Müller — Go to the Cloud — 43/49
  • 44. func fetcher(rw http.ResponseWriter, r *http.Request) { ctx := NewContext(r) client := urlfetch.Client(ctx) resp, err := client.Get("http://...") if err != nil { http.Error(rw, err.String(), http.StatusInternalServerError) return } ... } Come Together • Ressourcen via HTTP laden Frank Müller — Go to the Cloud — 44/49
  • 45. func mailer(rw http.ResponseWriter, r *http.Request) { ctx := NewContext(r) msg := &mail.Message{ Sender: "My App <my.app@mydomain.de>", To: "receiver@anydomain.de", Subject: "Thank you for your feedback", Body: feedbackText, } if err := mail.Send(ctx, msg); err != nil { http.Error(rw, err.String(), http.StatusInternalServerError) return } } Come Together • Mails senden Frank Müller — Go to the Cloud — 45/49
  • 46. Fazit
  • 47. Schneller Einstieg Einfache und leistungsfähige API Flexible Services Produktive Programmiersprache Transparente Skalierung Fazit • Vorteile Frank Müller — Go to the Cloud — 47/49
  • 48. Weniger flexibel als IaaS, Rackspace oder Hosting Einschränkungen in den Services und der API Bindung an die Plattform im Code Fazit • Nachteile Frank Müller — Go to the Cloud — 48/49