DevDay 2016: Adam Bien - Eine sprachneutrale Essenz der Microservices
Microservices mit Java und Go - DOAG Deutsche ORACLE ... · MMiiccrroosseerrvviiccee...
Transcript of Microservices mit Java und Go - DOAG Deutsche ORACLE ... · MMiiccrroosseerrvviiccee...
Microservices mit Java und GoMicroservices mit Java und GoMicroservices mit Java und GoJavaland 2019Javaland 2019Javaland 201920 March 201920 March 201920 March 2019
Johannes WeigendJohannes WeigendJohannes WeigendQAware GmbHQAware GmbHQAware GmbH
AboutAboutAbout
Trainer, Dozent, Software Architekt, CTO und FirmengründerTrainer, Dozent, Software Architekt, CTO und FirmengründerTrainer, Dozent, Software Architekt, CTO und Firmengründer
Java/C++/Go ProgrammiererJava/C++/Go ProgrammiererJava/C++/Go Programmierer
Java Certi�ed TrainerJava Certi�ed TrainerJava Certi�ed Trainer
Java Enterprise ArchitektJava Enterprise ArchitektJava Enterprise Architekt
Java RockstarJava RockstarJava Rockstar 222
AgendaAgendaAgenda
Java und Go im ÜberblickJava und Go im ÜberblickJava und Go im Überblick
Go Programmierung in a NutshellGo Programmierung in a NutshellGo Programmierung in a Nutshell
Microservice Entwicklung mit HTTP/JSON und plain GoMicroservice Entwicklung mit HTTP/JSON und plain GoMicroservice Entwicklung mit HTTP/JSON und plain Go
Microservice Entwicklung mit dem Gorilla ToolkitMicroservice Entwicklung mit dem Gorilla ToolkitMicroservice Entwicklung mit dem Gorilla Toolkit
Microservice Entwicklung mit Protocol Bu�ers und Google GRPCMicroservice Entwicklung mit Protocol Bu�ers und Google GRPCMicroservice Entwicklung mit Protocol Bu�ers und Google GRPC
Cloud Native Microservices mit go-kitCloud Native Microservices mit go-kitCloud Native Microservices mit go-kit
Best of Breed - Best of Breed - Best of Breed - Was verwendet man wann?Was verwendet man wann?Was verwendet man wann? 333
444
Go im ÜberblickGo im ÜberblickGo im Überblick
Go wurde als C/C++ Alternative zur Backendentwicklung bei Google entwickeltGo wurde als C/C++ Alternative zur Backendentwicklung bei Google entwickeltGo wurde als C/C++ Alternative zur Backendentwicklung bei Google entwickelt
Go ist eine Open Source Programmiersprache für verteilte und parallele SystemeGo ist eine Open Source Programmiersprache für verteilte und parallele SystemeGo ist eine Open Source Programmiersprache für verteilte und parallele Systeme(systemnah)(systemnah)(systemnah)
Das Go Kernteam ist prominent: Robert Griesheimer (Hotspot-VM), Ken ThompsonDas Go Kernteam ist prominent: Robert Griesheimer (Hotspot-VM), Ken ThompsonDas Go Kernteam ist prominent: Robert Griesheimer (Hotspot-VM), Ken Thompson(UX/B) und Rob Pike (UTF-8)(UX/B) und Rob Pike (UTF-8)(UX/B) und Rob Pike (UTF-8)
Go wird seit 2008 aktiv entwickelt (Aktuelle Version 1.11)Go wird seit 2008 aktiv entwickelt (Aktuelle Version 1.11)Go wird seit 2008 aktiv entwickelt (Aktuelle Version 1.11)
Go ist Go ist Go ist DIEDIEDIE Sprache hinter dem Cloud Native Stack. Siehe www.cncf.io Sprache hinter dem Cloud Native Stack. Siehe www.cncf.io Sprache hinter dem Cloud Native Stack. Siehe www.cncf.io
⇨⇨ Alle wesentlichen Komponenten sind in Go geschrieben: Docker, Kubernetes, Etcd, Alle wesentlichen Komponenten sind in Go geschrieben: Docker, Kubernetes, Etcd,⇨ Alle wesentlichen Komponenten sind in Go geschrieben: Docker, Kubernetes, Etcd,Prometheus, GrafanaPrometheus, GrafanaPrometheus, Grafana 555
Go im Überblick - DesignzieleGo im Überblick - DesignzieleGo im Überblick - Designziele
KISS (Schlüsselwörter: Go=25, KISS (Schlüsselwörter: Go=25, KISS (Schlüsselwörter: Go=25, Ansi-C=32, Java=50)Ansi-C=32, Java=50)Ansi-C=32, Java=50)
Compiler: Schnell, Cross Compiler, BinärcodeCompiler: Schnell, Cross Compiler, BinärcodeCompiler: Schnell, Cross Compiler, Binärcode
Realtime Garbage CollectionRealtime Garbage CollectionRealtime Garbage Collection
Statisches Typsystem mit Laufzeitunterstützung (Re�ection, Dynamic Types -> KeineStatisches Typsystem mit Laufzeitunterstützung (Re�ection, Dynamic Types -> KeineStatisches Typsystem mit Laufzeitunterstützung (Re�ection, Dynamic Types -> KeineGenerics)Generics)Generics)
Unterstützung von Nebenläu�gkeit, Parallelität und Verteilung (Multi-Core / Cloud)Unterstützung von Nebenläu�gkeit, Parallelität und Verteilung (Multi-Core / Cloud)Unterstützung von Nebenläu�gkeit, Parallelität und Verteilung (Multi-Core / Cloud)
Einfache Anbindung von C/C++ CodeEinfache Anbindung von C/C++ CodeEinfache Anbindung von C/C++ Code
Statischer Linker (Single Binary) Statischer Linker (Single Binary) ⇨⇨ Ideal für Docker Container Ideal für Docker ContainerStatischer Linker (Single Binary) ⇨ Ideal für Docker Container
Sprachfeatures aus modernen, dynamischen SprachenSprachfeatures aus modernen, dynamischen SprachenSprachfeatures aus modernen, dynamischen Sprachen
Unterstützt diverser Programmierstile (PP, OOP, FP)Unterstützt diverser Programmierstile (PP, OOP, FP)Unterstützt diverser Programmierstile (PP, OOP, FP)
Kompatibel!Kompatibel!Kompatibel!
⇨⇨ Go Programmierung soll Spaß machen! Go Programmierung soll Spaß machen!⇨ Go Programmierung soll Spaß machen! 666
Schwächen von Java im Kontext von Microservices ? (1/2)Schwächen von Java im Kontext von Microservices ? (1/2)Schwächen von Java im Kontext von Microservices ? (1/2)
RessourcenbedarfRessourcenbedarfRessourcenbedarf
Java Anwendungen haben einen hohen Grundbedarf an Ressourcen (RAM, CPU - StartupJava Anwendungen haben einen hohen Grundbedarf an Ressourcen (RAM, CPU - StartupJava Anwendungen haben einen hohen Grundbedarf an Ressourcen (RAM, CPU - StartupTime (verursacht durch Class Loading)).Time (verursacht durch Class Loading)).Time (verursacht durch Class Loading)).
DockerDockerDocker
Java Anwendungen benötigen zusätzlich eine JVM. Aufgrund der JVM AbhängigkeitenJava Anwendungen benötigen zusätzlich eine JVM. Aufgrund der JVM AbhängigkeitenJava Anwendungen benötigen zusätzlich eine JVM. Aufgrund der JVM Abhängigkeitenenthalten viele Docker Container ein komplettes OS Filesystem Image.enthalten viele Docker Container ein komplettes OS Filesystem Image.enthalten viele Docker Container ein komplettes OS Filesystem Image.
FootprintFootprintFootprint
Ein kleines Hadoop Tool benötigt aufgrund der JARs schnell 100 MB. Aufgrund derEin kleines Hadoop Tool benötigt aufgrund der JARs schnell 100 MB. Aufgrund derEin kleines Hadoop Tool benötigt aufgrund der JARs schnell 100 MB. Aufgrund derdynamischen ClassLoader Architektur kann erst zur Laufzeit entschieden werden welchedynamischen ClassLoader Architektur kann erst zur Laufzeit entschieden werden welchedynamischen ClassLoader Architektur kann erst zur Laufzeit entschieden werden welcheKlassen wirklich benötigt werden. Oft ist das nur ein kleiner Prozentsatz des vorhandenKlassen wirklich benötigt werden. Oft ist das nur ein kleiner Prozentsatz des vorhandenKlassen wirklich benötigt werden. Oft ist das nur ein kleiner Prozentsatz des vorhandenCodes.Codes.Codes. 777
Schwächen von Java im Kontext von Microservices ? (1/2)Schwächen von Java im Kontext von Microservices ? (1/2)Schwächen von Java im Kontext von Microservices ? (1/2)
ThreadsThreadsThreads
⇨⇨ Threads sind schwergewichtige Betriebssystem Ressourcen. Threads sind schwergewichtige Betriebssystem Ressourcen.⇨ Threads sind schwergewichtige Betriebssystem Ressourcen.
⇨⇨ Anwendungen können Threads blockieren. Anwendungen können Threads blockieren.⇨ Anwendungen können Threads blockieren.
⇨⇨ Thread Pools sind hier keine Lösung, da langlaufende Aktionen zur Blockade führen Thread Pools sind hier keine Lösung, da langlaufende Aktionen zur Blockade führen⇨ Thread Pools sind hier keine Lösung, da langlaufende Aktionen zur Blockade führenkönnen, falls mehr Anfragen bearbeitet müssen als Threads im Pool zur Verfügung stehen.können, falls mehr Anfragen bearbeitet müssen als Threads im Pool zur Verfügung stehen.können, falls mehr Anfragen bearbeitet müssen als Threads im Pool zur Verfügung stehen.
⇨⇨ Go hat Go Routinen. Die Logik in Go Routinen wird abschnittsweise auf Threads verteilt. Go hat Go Routinen. Die Logik in Go Routinen wird abschnittsweise auf Threads verteilt.⇨ Go hat Go Routinen. Die Logik in Go Routinen wird abschnittsweise auf Threads verteilt.Damit kann man um Faktoren mehr Go Routinen als Threads starten.Damit kann man um Faktoren mehr Go Routinen als Threads starten.Damit kann man um Faktoren mehr Go Routinen als Threads starten. 888
Daisy Chaining: 100.000 concurrent Go RoutinenDaisy Chaining: 100.000 concurrent Go RoutinenDaisy Chaining: 100.000 concurrent Go Routinen
Es macht Sinn sich Go also genauer anzusehen!Es macht Sinn sich Go also genauer anzusehen!Es macht Sinn sich Go also genauer anzusehen!
packagepackage main importimport "fmt" funcfunc f(left, right chanchan intint) { left <- 1 + <-right } funcfunc main() { constconst n = 100000 leftmost := make(chanchan intint) right := leftmost left := leftmost forfor i := 0; i < n; i++ { right = make(chanchan intint) gogo f(left, right) left = right } gogo funcfunc(c chanchan intint) { c <- 1 }(right) fmt.Println(<-leftmost) } Run
999
Go Programmierung in a NutshellGo Programmierung in a NutshellGo Programmierung in a Nutshell
101010
Hello World mit GoHello World mit GoHello World mit Go
Go Quelldateien sind UTF-8 kodiertGo Quelldateien sind UTF-8 kodiertGo Quelldateien sind UTF-8 kodiert
Package Namen sind nicht hierarchisch!Package Namen sind nicht hierarchisch!Package Namen sind nicht hierarchisch!
Package Importe sind vollquali�ziert, versioniert und hierarchisch!Package Importe sind vollquali�ziert, versioniert und hierarchisch!Package Importe sind vollquali�ziert, versioniert und hierarchisch!
Funktionen/Typen/Variablen die mit einem Großbuchstaben beginnen sind "public".Funktionen/Typen/Variablen die mit einem Großbuchstaben beginnen sind "public".Funktionen/Typen/Variablen die mit einem Großbuchstaben beginnen sind "public".
Kleingeschriebene Bezeichner sind im Package sichtbar. Es gibt kein "private".Kleingeschriebene Bezeichner sind im Package sichtbar. Es gibt kein "private".Kleingeschriebene Bezeichner sind im Package sichtbar. Es gibt kein "private".
packagepackage main importimport "fmt" funcfunc main() { fmt.Printf("Hello %s", "Programming with Go \xE2\x98\xAF\n") // \xE2\x98\xAF -> ☯ fmt.Printf("Hello %s", "Programming with Go ☯\n") } Run
111111
Funktionen und Kontrollstrukturen: Beispiel PalindromFunktionen und Kontrollstrukturen: Beispiel PalindromFunktionen und Kontrollstrukturen: Beispiel Palindrom
// IsPalindrome implementation. Does only work for 1-Byte UTF-8 chars (ASCII). funcfunc IsPalindrome(word stringstring) boolbool { forfor pos := 0; pos < len(word)/2; pos++ { ifif word[pos] != word[len(word)-pos-1] { returnreturn falsefalse } } returnreturn truetrue }
Es gibt ausschließlich for Schleifen (kein while, do)Es gibt ausschließlich for Schleifen (kein while, do)Es gibt ausschließlich for Schleifen (kein while, do)
Der Typ einer Variable steht hinter dem Namen!Der Typ einer Variable steht hinter dem Namen!Der Typ einer Variable steht hinter dem Namen!
Der Rückgabetyp einer Funktion steht hinter den Parametern!Der Rückgabetyp einer Funktion steht hinter den Parametern!Der Rückgabetyp einer Funktion steht hinter den Parametern!
Bedingungen werden nicht geklammertBedingungen werden nicht geklammertBedingungen werden nicht geklammert
if, for ... Blöcke sind grundsätzlich geklammert {}if, for ... Blöcke sind grundsätzlich geklammert {}if, for ... Blöcke sind grundsätzlich geklammert {}
Strichpunkte werden i.R. weggelassenStrichpunkte werden i.R. weggelassenStrichpunkte werden i.R. weggelassen 121212
Go kennt Pointer ähnlich zu C/C++Go kennt Pointer ähnlich zu C/C++Go kennt Pointer ähnlich zu C/C++
funcfunc swap1(x, y intint) { x, y = y, x }
funcfunc swap2(x *intint, y *intint) { *x, *y = *y, *x }
funcfunc swap3(x **intint, y **intint) { *x, *y = *y, *x }
Die doppelt Zuweisung spart eine Variable (tmp) ein!Die doppelt Zuweisung spart eine Variable (tmp) ein!Die doppelt Zuweisung spart eine Variable (tmp) ein!
Pointer werden wie auch Werte per Kopie übergebenPointer werden wie auch Werte per Kopie übergebenPointer werden wie auch Werte per Kopie übergeben
Es gibt keine Pointer Arithmetik (p++) wie in C/C++Es gibt keine Pointer Arithmetik (p++) wie in C/C++Es gibt keine Pointer Arithmetik (p++) wie in C/C++
Pointer sind automatisch mit nil initialisiertPointer sind automatisch mit nil initialisiertPointer sind automatisch mit nil initialisiert 131313
Go kennt Pointer ähnlich zu C/C++Go kennt Pointer ähnlich zu C/C++Go kennt Pointer ähnlich zu C/C++
funcfunc main() { varvar a, b = 1, 2 fmt.Printf("a=%d, b=%d\n", a, b) swap1(a, b) fmt.Printf("swap1(a,b) : a=%d, b=%d\n", a, b) swap2(&a, &b) fmt.Printf("swap2(&a,&b) : a=%d, b=%d\n", a, b) pa, pb := &a, &b swap3(&pa, &pb) fmt.Printf("swap3(&pa, &pb): a=%d, b=%d\n", a, b) } Run
141414
Warum Pointer?Warum Pointer?Warum Pointer?
Anbindung von C-Code ohne Adapter (Java JNI)Anbindung von C-Code ohne Adapter (Java JNI)Anbindung von C-Code ohne Adapter (Java JNI)
Unterscheidung zwischen Pointer und ValueUnterscheidung zwischen Pointer und ValueUnterscheidung zwischen Pointer und Value
Kontrolle über das Speicherlayout von Strukturen (siehe Project Valhalla bei Java)Kontrolle über das Speicherlayout von Strukturen (siehe Project Valhalla bei Java)Kontrolle über das Speicherlayout von Strukturen (siehe Project Valhalla bei Java)
Value Types (�ache Strukturen / analog zu C/C++)Value Types (�ache Strukturen / analog zu C/C++)Value Types (�ache Strukturen / analog zu C/C++)
typetype Point structstruct { x, y, z intint} typetype Triangle structstruct { a, b, c Point // flach a, b, c *Point // wie in Java: 3 Pointer } typetype TSlice [] Triangle
Immutability (Methoden können Objekte nicht ändern)Immutability (Methoden können Objekte nicht ändern)Immutability (Methoden können Objekte nicht ändern)
funcfunc (Triangle t) Translate(Point p) Triangle { returnreturn Triangle{t.a.move(p.x), t.b.move(p.y), t.c.move(p.z)} }
151515
Go kennt keine Klassen sondern Typen und FunktionenGo kennt keine Klassen sondern Typen und FunktionenGo kennt keine Klassen sondern Typen und Funktionen
// Rational represents a rational number numerator/denominator. typetype Rational structstruct { numerator intint denominator intint }
// Multiply method for rational numbers (x1/x2 * y1/y2) funcfunc (x Rational) Multiply(y Rational) Rational { returnreturn NewRational(x.numerator*y.numerator, x.denominator*y.denominator) }
161616
Go hat Unit Testing bereits eingebautGo hat Unit Testing bereits eingebautGo hat Unit Testing bereits eingebaut
funcfunc TestRational(t *testing.T) { r1 := NewRational(1, 2) r2 := NewRational(2, 4) // test equal ifif r1 != r2 { t.Error("1/2 should be equal to 2/4 but is not.") } // test multiply r3 := r1.Multiply(r2) ifif r3 != NewRational(1, 4) { t.Error(fmt.Sprintf("1/2 * 1/2 should be 1/4 but ist %v", r3)) } // test add r4 := r3.Add(r3) ifif r4 != NewRational(1, 2) { t.Error(fmt.Sprintf("1/4 + 1/4 should be 1/2 but ist %v", r4)) } }
171717
Der Basistyp "Object" ist in Go das leere Interface {}Der Basistyp "Object" ist in Go das leere Interface {}Der Basistyp "Object" ist in Go das leere Interface {}
// Stack is a generic LIFO container for untyped objects. typetype Stack structstruct { data []interfaceinterface{} } // NewStack constructs an empty stack. funcfunc NewStack() *Stack { returnreturn new(Stack) } // Push pushes a value on the stack. funcfunc (s *Stack) Push(value interfaceinterface{}) { s.data = append(s.data, value) } // Pop pops a value from the stack. It returns an error if the stack is empty. funcfunc (s *Stack) Pop() interfaceinterface{} { ifif len(s.data) == 0 { panic("can not pop: empty stack") } varvar result = s.data[len(s.data)-1] s.data = s.data[0 : len(s.data)-1] returnreturn result } // Size returns the count of elements in the Stack funcfunc (s *Stack) Size() intint {
returnreturn len(s.data) } // Get returns the n-th element in the Stack funcfunc (s *Stack) Get(idx intint) interfaceinterface{} { returnreturn s.data[idx] }
181818
Der Downcast wie bei Java sicherDer Downcast wie bei Java sicherDer Downcast wie bei Java sicher
funcfunc TestCasting(t *testing.T) { s := NewStack() s.Push(1) s.Push(2) sum := 0 forfor s.Size() > 0 { sum += s.Pop().(intint) // type assertion = cast from interface{} to int } ifif sum != 3 { t.Error(fmt.Sprintf("Sum result should be 3 but is %v", sum)) } }
191919
Go kennt Polymorphismus nur über InterfacesGo kennt Polymorphismus nur über InterfacesGo kennt Polymorphismus nur über Interfaces
// Sender is a interface to send mails. typetype Sender interfaceinterface { // Send an email with a message. SendMail(message stringstring) }
202020
Interfaces implementiert man durch Bereitstellung der gefordertenInterfaces implementiert man durch Bereitstellung der gefordertenInterfaces implementiert man durch Bereitstellung der gefordertenMethodenMethodenMethoden
// MailSenderImpl is a sender object. typetype MailSenderImpl structstruct { address mail.Address } // NewMailSender constructs a mail sender with a delivery address. funcfunc NewMailSender(address mail.Address) *MailSenderImpl { sender := new(MailSenderImpl) sender.address = address returnreturn sender } // SendMail sends a mail to a receiver. funcfunc (m *MailSenderImpl) SendMail(message stringstring) { log.Printf("Sending message with SMTP to %v. Message %s.", m.address, message) returnreturn }
212121
Das Go Interface kann wie in Java genutzt werdenDas Go Interface kann wie in Java genutzt werdenDas Go Interface kann wie in Java genutzt werden
// Package client contains sample code for the mail components. packagepackage client importimport "github.com/qaware/programmieren-mit-go/01_object-oriented-programming/mail/wire" // SendMail sends a mail to a receiver. funcfunc SendMail(message stringstring) { // Create an implementation for the mail.Sender interface. varvar sender = wire.InitializeSender() sender.SendMail(message) }
wire ist das Dependency Injection Framework des Go Cloud Development Kitwire ist das Dependency Injection Framework des Go Cloud Development Kitwire ist das Dependency Injection Framework des Go Cloud Development Kit
github.com/google/go-cloudgithub.com/google/go-cloudgithub.com/google/go-cloud (https://github.com/google/go-cloud) (https://github.com/google/go-cloud) (https://github.com/google/go-cloud) 222222
OOP mit GoOOP mit GoOOP mit Go
Mehrere Interfaces können zu einem Interface kombiniert werdenMehrere Interfaces können zu einem Interface kombiniert werdenMehrere Interfaces können zu einem Interface kombiniert werden
Go unterstützt keine Vererbung sondern Typ Embedding (Delegation ohneGo unterstützt keine Vererbung sondern Typ Embedding (Delegation ohneGo unterstützt keine Vererbung sondern Typ Embedding (Delegation ohnesyntaktischem Ballast)syntaktischem Ballast)syntaktischem Ballast)
Go unterstützt Polymorphismus nur über Interfaces nicht über EmbeddingGo unterstützt Polymorphismus nur über Interfaces nicht über EmbeddingGo unterstützt Polymorphismus nur über Interfaces nicht über Embedding
Die Interface Hierarchie ist von der Typ Hierarchie komplett unabhängigDie Interface Hierarchie ist von der Typ Hierarchie komplett unabhängigDie Interface Hierarchie ist von der Typ Hierarchie komplett unabhängig 232323
Go WerkzeugkastenGo WerkzeugkastenGo Werkzeugkasten
Compile, Build, Run von Anwendungen aus vielen Packages / QuelldateienCompile, Build, Run von Anwendungen aus vielen Packages / QuelldateienCompile, Build, Run von Anwendungen aus vielen Packages / Quelldateien
Unit Testing mit Test CoverageUnit Testing mit Test CoverageUnit Testing mit Test Coverage
Pro�ling mit pprof (CPU und Memory) -> FlamegraphsPro�ling mit pprof (CPU und Memory) -> FlamegraphsPro�ling mit pprof (CPU und Memory) -> Flamegraphs
Formatierung von Quelldateien mit go fmtFormatierung von Quelldateien mit go fmtFormatierung von Quelldateien mit go fmt
Quellcode Style Checker mit go vetQuellcode Style Checker mit go vetQuellcode Style Checker mit go vet
Slideshows mit ausführbarem Go Code im BrowserSlideshows mit ausführbarem Go Code im BrowserSlideshows mit ausführbarem Go Code im Browser
.........
Flame Graphruntim..
ru..strings.. r..runtime.mallocgc (489 ..
all
r..
ru..
github.com/uber/gotorch/graph..pathAsString (7.49s) (3,276 samples, 98.67%)
strings.Replace (1,784 samples, 53.73%) runtime.concatstrings..b..
runtime.rawstring (648 samples, ..
runtim..
runtime.rawstrin..
runtim..
bytes..
runtime.makeslice (489..
r..
r..runtime.slicebytetostring (805 samples, 24..r..
ru..
runtime.m..
github.com/uber/gotorch/graph..dfs (7.73s) (3,288 samples, 99.04%)
r..run..
runtime.mal..
runtim..
r..st..
r..
runtim..
st..
r..runtime.newarray (489 ..
runtime.m..r..
runtime.concatstring2..runtime.rawst..r..
run..runtim..
strings..r..
runt..
strings..
runtime.mallocgc (489 ..
runti..
runtime..runtim..
runtime.slicebytet..
r..
runtim..
st..r..
github.com/uber/gotorch/graph.getFormattedFunctionLabel (2,012 samples, 60.60%)
r..run..ru..
242424
Microservices mit GoMicroservices mit GoMicroservices mit Go
252525
RESTful Services mit JSON/XML - Das net/http PackageRESTful Services mit JSON/XML - Das net/http PackageRESTful Services mit JSON/XML - Das net/http Package
packagepackage main importimport ( "log" "net/http" ) funcfunc main() { router := http.NewServeMux() router.HandleFunc("/customers", getAllCustomers) log.Println("CustomerServer: Listening on http://localhost:8080/customers ...") log.Fatal(http.ListenAndServe(":8080", router)) }
Als Router wird der Go HTTP Mulitplexer verwendet (mux)Als Router wird der Go HTTP Mulitplexer verwendet (mux)Als Router wird der Go HTTP Mulitplexer verwendet (mux)
Der Router/Multiplexer leitet URL Aufrufe an eine Handlerfunktion weiterDer Router/Multiplexer leitet URL Aufrufe an eine Handlerfunktion weiterDer Router/Multiplexer leitet URL Aufrufe an eine Handlerfunktion weiter 262626
HandlerHandlerHandler
// Customer type typetype Customer structstruct { Name stringstring `json:"name"` Address stringstring `json:"adress"` Tel stringstring `json:"tel"` } // Static customer data. varvar customers = []Customer{ Customer{"QAware GmbH", "Munich", "+49 000 12345678"}, Customer{"QAware GmbH", "Mainz", "+49 111 87654321"}, } // Handler to get all customers encoded as JSON funcfunc getAllCustomers(w http.ResponseWriter, r *http.Request) { ifif err := json.NewEncoder(w).Encode(customers); err != nilnil { panic(err) } }
Das JSON oder XML Marshalling wird über Kommentare gesteuertDas JSON oder XML Marshalling wird über Kommentare gesteuertDas JSON oder XML Marshalling wird über Kommentare gesteuert
Kommentare sind der Ersatz für Annotationen bei JavaKommentare sind der Ersatz für Annotationen bei JavaKommentare sind der Ersatz für Annotationen bei Java 272727
Go und Docker - Das Builder PatternGo und Docker - Das Builder PatternGo und Docker - Das Builder Pattern
# Build FROM golang:alpine as builder RUN mkdir /build ADD . /build/ WORKDIR /build RUN CGO_ENABLED=0 GOOS=linux gogo build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o main . # Repackage FROM scratch COPY --from=builder /build/main /app/ WORKDIR /app CMD ["./main"]
Der Container "builder" enthält die komplette Go Compiler Suite + ToolsDer Container "builder" enthält die komplette Go Compiler Suite + ToolsDer Container "builder" enthält die komplette Go Compiler Suite + Tools
Der generierte Container enthält ausschließlich das von Go generierte ProgrammDer generierte Container enthält ausschließlich das von Go generierte ProgrammDer generierte Container enthält ausschließlich das von Go generierte Programm
Das Programm ist statisch gelinkt und hat keine weiteren AbhängigkeitenDas Programm ist statisch gelinkt und hat keine weiteren AbhängigkeitenDas Programm ist statisch gelinkt und hat keine weiteren Abhängigkeiten
Der �nale Container ist damit wenige MB groß!!!Der �nale Container ist damit wenige MB groß!!!Der �nale Container ist damit wenige MB groß!!! 282828
DEMODEMODEMO
# Makefile docker: docker build -t customer-service . docker images | grep customer-service dockerrun: docker run -p8080:8080 customer-service /app/main
$ make docker ... Successfully tagged customer-service:latest docker images | grep customer-service customer-service latest 5e7e9794779a Less than a second ago 7,03MB
292929
Microservices nach dem ZwiebelmodelMicroservices nach dem ZwiebelmodelMicroservices nach dem Zwiebelmodel
Das Onion Modell fokussiert auf einen unabhängigen Anwendungskern der dieDas Onion Modell fokussiert auf einen unabhängigen Anwendungskern der dieDas Onion Modell fokussiert auf einen unabhängigen Anwendungskern der dietechnikfreie Businesslogik kapselttechnikfreie Businesslogik kapselttechnikfreie Businesslogik kapselt
Abhängigkeiten in der Businesslogik sind über fachliche Schnittstellen abstrahiert (z.B.Abhängigkeiten in der Businesslogik sind über fachliche Schnittstellen abstrahiert (z.B.Abhängigkeiten in der Businesslogik sind über fachliche Schnittstellen abstrahiert (z.B.ProductRepository für den DB Zugri�)ProductRepository für den DB Zugri�)ProductRepository für den DB Zugri�)
Die Implementierungen dieser Schnittstellen liegen außen!Die Implementierungen dieser Schnittstellen liegen außen!Die Implementierungen dieser Schnittstellen liegen außen! 303030
Das Gorilla Webframework vereinfacht die Erstellung von WebservicesDas Gorilla Webframework vereinfacht die Erstellung von WebservicesDas Gorilla Webframework vereinfacht die Erstellung von Webservices
"github.com/gorilla/handlers" "github.com/qaware/programmieren-mit-go/04_distributed-programming/products/web" ) funcfunc main() { port := os.Getenv("PORT") ifif port == "" { port = "8080" } router := web.NewRouter() // create routes // These lines are important in order to allow access from the front-end side to the methods allowedOrigins := handlers.AllowedOrigins([]stringstring{"*"}) allowedMethods := handlers.AllowedMethods([]stringstring{"GET", "POST", "DELETE", "PUT"}) allowedHeaders := handlers.AllowedHeaders([]stringstring{"X-Requested-With"}) // Launch server with CORS validations log.Printf("ProductServer: Listening on http://localhost:%s/", port) log.Fatal(http.ListenAndServe(":"+port, handlers.CORS(allowedOrigins, allowedMethods, allowedHeaders
313131
Routing mit Gorilla mux (1/2)Routing mit Gorilla mux (1/2)Routing mit Gorilla mux (1/2)
// Route defines a route typetype Route structstruct { Name stringstring Method stringstring Pattern stringstring HandlerFunc http.HandlerFunc } // Routes defines the list of routes of our API typetype Routes []Route varvar routes = Routes{ Route{ "Index", "GET", "/", controller.Index, }, Route{ "AddProduct", "POST", "/AddProduct", controller.AddProduct, }, Route{ "UpdateProduct", "PUT",
"/UpdateProduct", controller.UpdateProduct, }, // Get Product by {id} Route{ "GetProduct", "GET", "/Products/{id}", controller.GetProduct, }, // Delete Product by {id} Route{ "DeleteProduct", "DELETE", "/DeleteProduct/{id}", controller.DeleteProduct, }, // Search product with string Route{ "SearchProduct", "GET", "/Search/{query}", controller.SearchProduct, }} // NewRouter configures a new router to the API funcfunc NewRouter() *mux.Router { router := mux.NewRouter().StrictSlash(truetrue) forfor _, route := rangerange routes { varvar handler http.Handler
log.Printf("Installing route: %s, method: %s, pattern: %s", route.Name, route.Method, route.Pattern, ) handler = route.HandlerFunc router. Methods(route.Method). Path(route.Pattern). Name(route.Name). Handler(handler) } returnreturn router }
323232
Routing mit Gorilla mux (2/2)Routing mit Gorilla mux (2/2)Routing mit Gorilla mux (2/2)
// NewRouter configures a new router to the API funcfunc NewRouter() *mux.Router { router := mux.NewRouter().StrictSlash(truetrue) forfor _, route := rangerange routes { varvar handler http.Handler log.Printf("Installing route: %s, method: %s, pattern: %s", route.Name, route.Method, route.Pattern, ) handler = route.HandlerFunc router. Methods(route.Method). Path(route.Pattern). Name(route.Name). Handler(handler) } returnreturn router }
333333
Der Controller verbindet Web- und BusinesslogikDer Controller verbindet Web- und BusinesslogikDer Controller verbindet Web- und Businesslogik
// Controller implements the router functions. typetype Controller structstruct { Repository domain.Repository // injected! } // Index GET / => All products funcfunc (c *Controller) Index(w http.ResponseWriter, r *http.Request) { products := c.Repository.GetProducts() // Calls business logic ! data, _ := json.Marshal(products) w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) w.Write(data) returnreturn } // AddProduct POST /
343434
353535
AlternativenAlternativenAlternativen
Die Implementierung ist Low Level (�exibel aber aufwändig)Die Implementierung ist Low Level (�exibel aber aufwändig)Die Implementierung ist Low Level (�exibel aber aufwändig)
Alternative 1: Generierter Weblayer mit go-swaggerAlternative 1: Generierter Weblayer mit go-swaggerAlternative 1: Generierter Weblayer mit go-swagger
goswagger.io/goswagger.io/goswagger.io/ (https://goswagger.io/) (https://goswagger.io/) (https://goswagger.io/)
Alternative 2: Google gRPCAlternative 2: Google gRPCAlternative 2: Google gRPC
Alternative 3: Microservice Frameworks: micro, go-kit ...Alternative 3: Microservice Frameworks: micro, go-kit ...Alternative 3: Microservice Frameworks: micro, go-kit ... 363636
Microservices mit mit Go und gRPCMicroservices mit mit Go und gRPCMicroservices mit mit Go und gRPC
Google gRPC ist ein binärer und e�zienter RPC auf Basis von Protocolbu�ersGoogle gRPC ist ein binärer und e�zienter RPC auf Basis von Protocolbu�ersGoogle gRPC ist ein binärer und e�zienter RPC auf Basis von Protocolbu�ers
gRPC hat Bindings zu allen gängigen Programmiersprachen (auch JS!)gRPC hat Bindings zu allen gängigen Programmiersprachen (auch JS!)gRPC hat Bindings zu allen gängigen Programmiersprachen (auch JS!)
gRPC unterstützt synchronen RPC, Streaming (client/server), Timeouts, Canceling, HTTP 2gRPC unterstützt synchronen RPC, Streaming (client/server), Timeouts, Canceling, HTTP 2gRPC unterstützt synchronen RPC, Streaming (client/server), Timeouts, Canceling, HTTP 2
gRPC ist ideal für die Service zu Service KommunikationgRPC ist ideal für die Service zu Service KommunikationgRPC ist ideal für die Service zu Service Kommunikation 373737
Beispiel Nummernserver mit gRPCBeispiel Nummernserver mit gRPCBeispiel Nummernserver mit gRPC
Go Schnittstellende�nitionGo Schnittstellende�nitionGo Schnittstellende�nition
// Package idserv contains the IDService API. packagepackage idserv // IDService can be used to produce network wide unique ids. typetype IDService interfaceinterface { // NewUUID generates an UUID with a given client prefix. NewUUID(clientID stringstring) stringstring }
383838
Go Client und ImplementierungGo Client und ImplementierungGo Client und Implementierung
// GenerateIds calls n-times NewUUID() in a loop and returns the result as slice. funcfunc GenerateIds(count intint, service idserv.IDService) []stringstring { result := make([]stringstring, count) forfor i := 0; i < count; i++ { result[i] = service.NewUUID("c1") } returnreturn result }
typetype IDServiceImpl structstruct { } varvar lastID int64int64 // The last given Id. // NewIDServiceImpl creates a new instance funcfunc NewIDServiceImpl() *IDServiceImpl { returnreturn new(IDServiceImpl) } // NewUUID implements the IDService interface. funcfunc (ids *IDServiceImpl) NewUUID(clientID stringstring) stringstring { result := atomic.AddInt64(&lastID, 1) returnreturn fmt.Sprintf("%v:%v", clientID, result) }
393939
Die gRPC Protokollbuffer Definition idserv.protoDie gRPC Protokollbuffer Definition idserv.protoDie gRPC Protokollbuffer Definition idserv.proto
// The gRPC protobuf service definition service IDService { // NewUUID generates a globally unique ID rpc NewUUID (IdRequest) returns (IdReply) {} } // The client sends a unique id. message IdRequest { stringstring clientId = 1; } // The response message contains the uuid. message IdReply { stringstring uuid = 1; }
gogo get -u google.golang.org/grpc --> install GRPC gogo get -u github.com/golang/protobuf/protoc-gen-gogo --> install Protoc Go Plugin protoc -I remote/idserv/ remote/idserv/idserv.proto --go_out=plugins=grpc:remote/idserv
404040
Der Protokollcompiler generiert idserv.pb.goDer Protokollcompiler generiert idserv.pb.goDer Protokollcompiler generiert idserv.pb.go
// IDServiceServer is the server API for IDService service. typetype IDServiceServer interfaceinterface { // NewUUID generates a globally unique ID NewUUID(context.Context, *IdRequest) (*IdReply, error) }
Schnittstellen zur Implementierung am ServerSchnittstellen zur Implementierung am ServerSchnittstellen zur Implementierung am Server
Generierte Client Stubs für den AufrufGenerierte Client Stubs für den AufrufGenerierte Client Stubs für den Aufruf
Generierter Marshaling CodeGenerierter Marshaling CodeGenerierter Marshaling Code 414141
Server main()Server main()Server main()
constconst ( port = ":50051" ) funcfunc main() { lis, err := net.Listen("tcp", port) ifif err != nilnil { log.Fatalf("failed to listen: %v", err) } s := grpc.NewServer() idserv.RegisterIDServiceServer(s, &stub.Stub{}) // Register reflection service on gRPC server. reflection.Register(s) ifif err := s.Serve(lis); err != nilnil { log.Fatalf("failed to serve: %v", err) } }
Die Server main() Funktion ist nicht generiert!Die Server main() Funktion ist nicht generiert!Die Server main() Funktion ist nicht generiert! 424242
ClientClientClient
funcfunc main() { conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) ifif err != nilnil { panic(fmt.Sprintf("did not connect: %v", err)) } c := idserv.NewIDServiceClient(conn) ctx, cancel := context.WithTimeout(context.Background(), time.Second) deferdefer cancel() r, err := c.NewUUID(ctx, &idserv.IdRequest{ClientId: "client"}) ifif err != nilnil { log.Printf("could not generate id: %v", err) r.Uuid = "" } uuid := r.Uuid log.Println(uuid) }
434343
"Modulith" On Demand - Das Proxy Pattern mit gRPC"Modulith" On Demand - Das Proxy Pattern mit gRPC"Modulith" On Demand - Das Proxy Pattern mit gRPC
444444
Der Proxy implementiert das API interfaceDer Proxy implementiert das API interfaceDer Proxy implementiert das API interface
// NewUUID implements the IDService interface. funcfunc (p *Proxy) NewUUID(clientID stringstring) stringstring { c := idserv.NewIDServiceClient(p.connection) ctx, cancel := context.WithTimeout(context.Background(), time.Second) deferdefer cancel() r, err := c.NewUUID(ctx, &idserv.IdRequest{ClientId: clientID}) ifif err != nilnil { log.Printf("could not generate id: %v", err) r.Uuid = "" }
Die generierte Go Funktion unterscheidet sich von einem lokalem FunktionsaufrufDie generierte Go Funktion unterscheidet sich von einem lokalem FunktionsaufrufDie generierte Go Funktion unterscheidet sich von einem lokalem Funktionsaufruf
Parameter, Returnwerte und Fehlerbehandlung sind unterschiedlichParameter, Returnwerte und Fehlerbehandlung sind unterschiedlichParameter, Returnwerte und Fehlerbehandlung sind unterschiedlich
Der Proxy übernimmt das MappingDer Proxy übernimmt das MappingDer Proxy übernimmt das Mapping
Der Proxy dient als Fehlerfassade, Cirquitbreaker, Monitoring Fassade, Cache ...Der Proxy dient als Fehlerfassade, Cirquitbreaker, Monitoring Fassade, Cache ...Der Proxy dient als Fehlerfassade, Cirquitbreaker, Monitoring Fassade, Cache ... 454545
Der Stub delegiert an das API interfaceDer Stub delegiert an das API interfaceDer Stub delegiert an das API interface
// Stub implements the idserv.IdServer GRPC server side typetype Stub structstruct{} // NewUUID implements idserv.IdService interface funcfunc (s *Stub) NewUUID(c context.Context, r *idserv.IdRequest) (*idserv.IdReply, error) { deferdefer funcfunc() { ifif err := recover(); err != nilnil { log.Printf("Recovered from panic %v", err) } }() service := core.NewIDServiceImpl() returnreturn &idserv.IdReply{Uuid: service.NewUUID(r.GetClientId())}, nilnil }
Aufruf der BusinesslogikAufruf der BusinesslogikAufruf der Businesslogik
Fehlerbehandlung auf KommunikationsebeneFehlerbehandlung auf KommunikationsebeneFehlerbehandlung auf Kommunikationsebene
AusnahmebehandlungAusnahmebehandlungAusnahmebehandlung
Technisches Setup (Logging, ...)Technisches Setup (Logging, ...)Technisches Setup (Logging, ...) 464646
474747
Was fehlt hier noch?Was fehlt hier noch?Was fehlt hier noch?
MetrikenMetrikenMetriken
Service LocatorService LocatorService Locator
TracingTracingTracing
MessagingMessagingMessaging
......... 484848
Cloud Native Microservices mit go-kitCloud Native Microservices mit go-kitCloud Native Microservices mit go-kit
github.com/go-kitgithub.com/go-kitgithub.com/go-kit (https://github.com/go-kit) (https://github.com/go-kit) (https://github.com/go-kit)
494949
Getting Started mit go-kit (Bug Tracking System)Getting Started mit go-kit (Bug Tracking System)Getting Started mit go-kit (Bug Tracking System)
gogo get github.com/kujtimiihoxha/kit # gogo-kit CLI
Neue Services anlegenNeue Services anlegenNeue Services anlegen
kit n s users kit n s bugs kit n s notification
Service Schnittstellen de�nierenService Schnittstellen de�nierenService Schnittstellen de�nieren
// UsersService describes the service. typetype UsersService interfaceinterface { // Add your methods here GetUserByMail(ctx context.Context, mailAddress stringstring) (user User, err error) } // User struct typetype User structstruct { Name stringstring Email stringstring ID stringstring }
505050
Getting Started mit go-kit (2)Getting Started mit go-kit (2)Getting Started mit go-kit (2)
// HTTP Handler generieren kit g s users // gRPC Handler generieren kit g s notification -t grpc // Run Service gogo run users/cmd/mail.gogo
- Der Generator ist nicht Teil des gogo-kit Frameworks - Der Generator liefert einen guten Anfang - Der Generator muss weiter verbessert werden (OpenSource!)
// Test curl -d '{"Email":"j@w"}' -H "Content-Type: application/json" -X POST http://localhost:8081/get-user-by-
515151
Microservices mit Go - ZusammenfassungMicroservices mit Go - ZusammenfassungMicroservices mit Go - Zusammenfassung
Die Go Standardbibliothek unterstützt Low Level NetzwerkprogrammierungDie Go Standardbibliothek unterstützt Low Level NetzwerkprogrammierungDie Go Standardbibliothek unterstützt Low Level Netzwerkprogrammierung
Mit Go lassen sich einfach RESTful Webservices bauenMit Go lassen sich einfach RESTful Webservices bauenMit Go lassen sich einfach RESTful Webservices bauen
Mit Go lassen sich einfach GRPC Webservices bauen und anbindenMit Go lassen sich einfach GRPC Webservices bauen und anbindenMit Go lassen sich einfach GRPC Webservices bauen und anbinden
Channels und Go Routinen vereinfachen parallele ServerprogrammierungChannels und Go Routinen vereinfachen parallele ServerprogrammierungChannels und Go Routinen vereinfachen parallele Serverprogrammierung
Es gibt diverse Microservice Frameworks aber keine Standards wie z.B. JavaEEEs gibt diverse Microservice Frameworks aber keine Standards wie z.B. JavaEEEs gibt diverse Microservice Frameworks aber keine Standards wie z.B. JavaEE
Der Reifegrad der Frameworks und Bibliotheken ist SEHR unterschiedlichDer Reifegrad der Frameworks und Bibliotheken ist SEHR unterschiedlichDer Reifegrad der Frameworks und Bibliotheken ist SEHR unterschiedlich 525252
Für welche Anwendungen eignet sich Go?Für welche Anwendungen eignet sich Go?Für welche Anwendungen eignet sich Go?
Hilfsprozesse wie Sidecar Container auf Cloud Plattformen (Kubernetes, OpenShift)Hilfsprozesse wie Sidecar Container auf Cloud Plattformen (Kubernetes, OpenShift)Hilfsprozesse wie Sidecar Container auf Cloud Plattformen (Kubernetes, OpenShift)
Systemnahe Infrastrukturdienste wie Reverse Proxies, Authentication ProxiesSystemnahe Infrastrukturdienste wie Reverse Proxies, Authentication ProxiesSystemnahe Infrastrukturdienste wie Reverse Proxies, Authentication Proxies
Automationsfunktionalität in der Cloud wie Elastic Scaling AutomationAutomationsfunktionalität in der Cloud wie Elastic Scaling AutomationAutomationsfunktionalität in der Cloud wie Elastic Scaling Automation
Aggregator Dienste wie Backend for Frontend MicroservicesAggregator Dienste wie Backend for Frontend MicroservicesAggregator Dienste wie Backend for Frontend Microservices
Infrastruktur Dienste wie Monitoring, Logging ...Infrastruktur Dienste wie Monitoring, Logging ...Infrastruktur Dienste wie Monitoring, Logging ... 535353
Für welche Anwendungen sollte man Java wählen?Für welche Anwendungen sollte man Java wählen?Für welche Anwendungen sollte man Java wählen?
Anwendungen mit komplexen SchnittstellenAnwendungen mit komplexen SchnittstellenAnwendungen mit komplexen Schnittstellen
Große Enterprise Anwendungen mit langer Lebensdauer (Standards !)Große Enterprise Anwendungen mit langer Lebensdauer (Standards !)Große Enterprise Anwendungen mit langer Lebensdauer (Standards !)
Anwendungen mit einem hohen Wiederverwendungspotential durch vorhandene OpenAnwendungen mit einem hohen Wiederverwendungspotential durch vorhandene OpenAnwendungen mit einem hohen Wiederverwendungspotential durch vorhandene OpenSource ProjekteSource ProjekteSource Projekte 545454
Die Grauzone hängt von den Entwicklern und Strategie abDie Grauzone hängt von den Entwicklern und Strategie abDie Grauzone hängt von den Entwicklern und Strategie ab
Entwickler die bisher C++ und Java programmiert haben werden Go mögen und schnellEntwickler die bisher C++ und Java programmiert haben werden Go mögen und schnellEntwickler die bisher C++ und Java programmiert haben werden Go mögen und schnellproduktiv seinproduktiv seinproduktiv sein
Entwickler die bisher nur Java programmiert haben sollten mit Go eher vorsichtig seinEntwickler die bisher nur Java programmiert haben sollten mit Go eher vorsichtig seinEntwickler die bisher nur Java programmiert haben sollten mit Go eher vorsichtig sein
Firmen die sich stark in Richtung Cloud Nativer Entwicklung orientieren sollten mit GoFirmen die sich stark in Richtung Cloud Nativer Entwicklung orientieren sollten mit GoFirmen die sich stark in Richtung Cloud Nativer Entwicklung orientieren sollten mit Gomutiger seinmutiger seinmutiger sein 555555
Was kann man als Java Programmierer von Go lernen?Was kann man als Java Programmierer von Go lernen?Was kann man als Java Programmierer von Go lernen?
Message Passing ist mit Java auch ohne native Channels und Go Routinen möglich. HierMessage Passing ist mit Java auch ohne native Channels und Go Routinen möglich. HierMessage Passing ist mit Java auch ohne native Channels und Go Routinen möglich. Hierkann man von Go und der Einfachheit der Nutzung lernen.kann man von Go und der Einfachheit der Nutzung lernen.kann man von Go und der Einfachheit der Nutzung lernen.
KISS ist relevant. In Java ist inzwischen möglich ähnlich komplexen Code zu schreiben wieKISS ist relevant. In Java ist inzwischen möglich ähnlich komplexen Code zu schreiben wieKISS ist relevant. In Java ist inzwischen möglich ähnlich komplexen Code zu schreiben wiefrüher in C++. Guter Java Code beschränkt sich auf das wesentliche. Es ist nichtfrüher in C++. Guter Java Code beschränkt sich auf das wesentliche. Es ist nichtfrüher in C++. Guter Java Code beschränkt sich auf das wesentliche. Es ist nichtzielführend jedes Java Feature in eine Anwendung einzubauen!zielführend jedes Java Feature in eine Anwendung einzubauen!zielführend jedes Java Feature in eine Anwendung einzubauen!
Semantik Versioning und Minimal Version Detection sind Konzepte die sich auch mit JavaSemantik Versioning und Minimal Version Detection sind Konzepte die sich auch mit JavaSemantik Versioning und Minimal Version Detection sind Konzepte die sich auch mit JavaTools umsetzen lassen.Tools umsetzen lassen.Tools umsetzen lassen.
Es lassen sich mit ein wenig Erfahrung auch kleine, cloudfähige Java Container bauen.Es lassen sich mit ein wenig Erfahrung auch kleine, cloudfähige Java Container bauen.Es lassen sich mit ein wenig Erfahrung auch kleine, cloudfähige Java Container bauen.Hier kann man sich an Go orientieren.Hier kann man sich an Go orientieren.Hier kann man sich an Go orientieren.
Man sollte sich im Projekt überlegen, was man aus Java alles weglassen kann ohne anMan sollte sich im Projekt überlegen, was man aus Java alles weglassen kann ohne anMan sollte sich im Projekt überlegen, was man aus Java alles weglassen kann ohne anProduktivität und Spass zu verlieren.Produktivität und Spass zu verlieren.Produktivität und Spass zu verlieren. 565656
575757
Literatur und LinksLiteratur und LinksLiteratur und Links
Die Autoren von GoDie Autoren von GoDie Autoren von Go
de.wikipedia.org/wiki/Ken_Thompsonde.wikipedia.org/wiki/Ken_Thompsonde.wikipedia.org/wiki/Ken_Thompson (https://de.wikipedia.org/wiki/Ken_Thompson) (https://de.wikipedia.org/wiki/Ken_Thompson) (https://de.wikipedia.org/wiki/Ken_Thompson)
de.wikipedia.org/wiki/Rob_Pikede.wikipedia.org/wiki/Rob_Pikede.wikipedia.org/wiki/Rob_Pike (https://de.wikipedia.org/wiki/Rob_Pike) (https://de.wikipedia.org/wiki/Rob_Pike) (https://de.wikipedia.org/wiki/Rob_Pike)
Entstehung von GoEntstehung von GoEntstehung von Go
talks.golang.org/2015/gophercon-goevolution.slidetalks.golang.org/2015/gophercon-goevolution.slidetalks.golang.org/2015/gophercon-goevolution.slide (https://talks.golang.org/2015/gophercon-goevolution.slide) (https://talks.golang.org/2015/gophercon-goevolution.slide) (https://talks.golang.org/2015/gophercon-goevolution.slide)
www.youtube.com/watch?v=0ReKdcpNyQgwww.youtube.com/watch?v=0ReKdcpNyQgwww.youtube.com/watch?v=0ReKdcpNyQg (https://www.youtube.com/watch?v=0ReKdcpNyQg) (https://www.youtube.com/watch?v=0ReKdcpNyQg) (https://www.youtube.com/watch?v=0ReKdcpNyQg)
WerkzeugeWerkzeugeWerkzeuge
golang.org/pkg/net/http/pprofgolang.org/pkg/net/http/pprofgolang.org/pkg/net/http/pprof (https://golang.org/pkg/net/http/pprof) (https://golang.org/pkg/net/http/pprof) (https://golang.org/pkg/net/http/pprof)
github.com/uber/go-torchgithub.com/uber/go-torchgithub.com/uber/go-torch (https://github.com/uber/go-torch) (https://github.com/uber/go-torch) (https://github.com/uber/go-torch)
ConcurrencyConcurrencyConcurrency
talks.golang.org/2012/concurrency.slidetalks.golang.org/2012/concurrency.slidetalks.golang.org/2012/concurrency.slide (https://talks.golang.org/2012/concurrency.slide) (https://talks.golang.org/2012/concurrency.slide) (https://talks.golang.org/2012/concurrency.slide) 585858
Thank youThank youThank you
Johannes WeigendJohannes WeigendJohannes WeigendQAware GmbHQAware GmbHQAware [email protected]@[email protected] (mailto:[email protected]) (mailto:[email protected]) (mailto:[email protected])
@jweigend@jweigend@jweigend (http://twitter.com/jweigend) (http://twitter.com/jweigend) (http://twitter.com/jweigend)