4. • Go ist langweilig
• Go folgt keinem klaren Paradigma
• Go bietet keine esoterischen Features
• Go bietet nichts wirklich Neues
• Go ist nicht perfekt
• Go beinhaltet Stolpersteine
5. ABER
• Go ist einfach (Language Specification nur eine HTML Seite)
• Go bringt eine umfangreiche Bibliothek mit sich
• Go kompiliert sehr schnell in ein Binary
• Go beherrscht Cross-Compiling
• Go verfügt über Garbage Collection
• Go führt sehr schnell aus
• Go ist pragmatisch
8. Historie
• Start Ende 2007 aus Frust
• FAQ: „One had to choose either efficient compilation, efficient
execution, or ease of programming; all three were not available
in the same mainstream language.“
• Beginn der Entwicklung Mitte 2008
• Erste öffentliche Vorversion im November 2009
• Version 1.0 im März 2012
9. –Rob Pike
„Go aims to combine the safety and performance of a
statically typed compiled language with the
expressiveness and convenience of a dynamically typed
interpreted language.
It also aims to be suitable for modern systems – large
scale – programming.“
10. Das Team
• Rob Pike
• Ken Thompson
• Robert Griesemer
• Russ Cox
• Ian Lance Taylor
• Und weitere ...
11. Keine Unbekannten
• Ken Thompson — Multics, Unix, B, Plan 9, ed, UTF-8, etc. sowie
Turing Award
• Rob Pike — Unix, Plan 9, Inferno, Limbo, UTF-8, etc.
• Robert Griesemer — Strongtalk, Java HotSpot VM, V8
JavaScript Engine
12. Fortschritt
• 2014 wurde der der Gopher das Maskottchen von Go;
entworfen von Renée French, der Ehefrau von Rob Pike
• Alle 6 Monate erscheint ein neues Release
• Aktuell Version 1.12.5
• Versprechen der Sprachkompatibilität gleicher Hauptversionen
• Go 2 in Diskussion
14. Drei Binaries
• go — Wichtigstes Werkzeug mit vielen Subcommands
• gofmt — Einheitliche Formatierung der Go Quellen
• godoc — Generierung von Dokumentation aus Kommentaren
15. go Subcommands (Auszug)
• build — Compiling der Quellen
• fmt — Formattierung der Quellen
• get — Packages herunterladen und installieren
• install — Compiling und Installation der Quellen
• mod — Verwaltung von Modulen
• test — Durchführung der Unit Tests
• vet — Bericht über gängige Fehler
16. go mod Subcommands (Auszug)
• download — Download von Modulen in lokalen Cache
• init — Initialisierung eines Moduls im aktuellen Verzeichnis
• tidy — Bereinigung der Abhängigkeiten
• vendor — Vendorize von Abhängigkeiten
• why — Erläuterung von Abhängigkeiten
18. Orientierung in Packages
• Code immer in Packages
• Ein oder mehrere Dateien pro Package in einem Verzeichnis
• Sonderrollen
• main wird zu ausführbarem Programm
• <name>_test wird zu Unit Test von Package <name>
• Packages lassen sich hierarchisch schachteln
19. // main wird zu Programm mit dem Namen des Verzeichnisses.
package main
// Einstieg in das Programm.
func main() {
println("Hello, World!")
}
20. Import von Packages
• Import als erste Anweisung nach dem Package Statement
• Externe Packages enthalten Domain und Pfad
• Eigene Domains mit Code auf z.B. GitHub sind via Meta Tags in
einem lokalen HTML-Dokument ebenfalls möglich
• Package-Name als Präfix für Namensräume
• Alias kann gegen Namensgleichheit gesetzt werden
• Export durch Großschreibung, sonst package private
22. Funktionen
• Schlüsselwort func
• Mit Namen, anonym oder als Methode eigener Typen
• Beliebige Anzahl Parameter, letzter kann variadisch sein
• Beliebige Anzahl Rückgabewerte ohne und mit Namen
• Rückgabe mit Schlüsselwort return
23. // Mul multipliziert f mit einer beliebigen Anzahl
// Integer.
func Mul(f int, vs ...int) int {
r := f
for _, v := range vs {
r *= v
}
return r
}
24. // Div dividiert f ganzzahlig durch eine beliebige Anzahl
// Integer.
func Div(f int, vs ...int) (int, error) {
r := f
for _, v := range vs {
if v == 0 {
return 0, errors.New("division by zero")
}
r /= v
}
return r, nil
}
25. // Server ist ein Typ mit privaten Feldern.
type Server struct {
port int
...
}
// Option ist eine Funktion, die auf einem Server operiert.
type Option func(s *Server)
26. // Port liefert eine Option zum Setzen des Felds port
// zurück.
func Port(port int) Option {
return func(s *Server) {
s.port = port
}
}
27. // New erzeugt einen Server. Optionen sind ... optional. ;)
func New(opts ...Option) *Server {
s := &Server{
port: 12345, // Standardwert.
...
}
for _, opt := range opts {
opt(s)
}
return s
}
31. type StringProducer func() []string
func (sp StringProducer) Len() int {
return len(sp())
}
// Sizer definiert in meinem Package, was ich von einem
// Typ benötige.
type Sizer interface {
Len() int
}
func SizePrinter(sizer Sizer) { ... }
32. type Honk interface {
Honk() string
}
// Car bettet Honk ein, geht mit Structs und Interfaces.
type Car struct {
Honk
motor *Motor
...
}
myCar.Honk()
33. // Handler in Package net/http definiert einen Handler für
// Web Requests.
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
// ListenAndServe startet den Server mit einem Handler.
func ListenAndServe(addr string, handler Handler) error
34. // HandlerFunc vereinfach den Handler zu nur einer Funktion.
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP implementiert den Handler und führt nur die
// Handler-Funktion aus.
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
35. // ServeMux verteilt auf Handler nach Pfaden.
type ServeMux struct {
...
}
func (mux *ServeMux) Handle(pattern string, handler Handler) {
...
}
// ServeHTTP implementiert Handler.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
...
}
36. Von einfachem Interface zu mehr
• Multiplexer für HTTP Methoden
• Multiplexer für Schachtelung bei RESTful APIs
• Schachtelung für Trennung von Authentisierung/Autorisierung
via JSON Web Tokens o.ä.
37. Variablen explizit und implizit
• Mit Deklaration via var oder mit Zuweisung durch :=
• Typisierung explizit oder implizit
• var kennt beides, := ist immer implizit
• Zuweisung mit =
38. var s1 string // Deklaration
s1 = "Hello" // Zuweisung
var s2 string = "World" // Explizit mit Zuweisung
var s3 = s1 + ", " + s2 // Implizit mit Zuweisung
s4 := s3 + "!" // Deklaration implizit mit
// Zuweisung
40. Bedingungen
• Mit if oder switch für logische Bedingungen
• Mit select für Channel
• switch und select kennen default an beliebiger Stelle
• break nicht notwendig
• switch verfügt über fallthrough für die Ausführung der
Folgebedingung
41. if x > y {
x, y = y, x
}
if myFunctionReturnsTrue() {
fmt.Println("Juchu!")
} else {
fmt.Println("Schade")
}
42. switch x {
case 1, 2, 3:
fmt.Println("1 bis 3")
// Verpönte Weiterverarbeitung!
fallthrough
case 4, 5, 6:
fmt.Println("4 bis 6")
default:
fmt.Println("Keine Ahnung")
}
43. // Abarbeitung von oben nach unten, aber default immer nur
// wenn nichts passt.
switch {
case x < 0:
fmt.Println("Kleiner als 0")
default:
fmt.Println("Ha! Genau 0")
case x > 0:
fmt.Println("Größer als 0")
}
44. select {
case <-ctx.Done()
return ctx.Err()
case job := <-jobs:
if err := job(); err != nil {
log.Printf("job failed: %v", err)
}
case <-time.Tick(5 * time.Second):
log.Printf("I'm waiting ...")
}
45. Schleifen
• Schlüsselwort for
• Verschiedene Formen der Bedingungen
• Vorzeitige Fortsetzung über continue
• Vorzeitiges Verlassen über break
• Label für geschachtelte Schleifen
• Arrays, Slices, Maps und Channel können mit range iteriert
werden
47. for i := 0; i < 2019; i++ {
if i % 2 == 0 {
continue
}
...
}
visitors := visitorsByConference("JAX 2019")
for i, visitor := range visitors {
fmt.Printf("Besucher %d ist %sn", i, visitor.Name)
}
49. Nebenläufigkeit
• Leichtgewichtige Funktionen (Goroutinen) im Thread Pool
• Schnelle Kontextwechsel
• Kommunikation über typisierte Channel
• Abfrage mehrerer Channel gleichzeitig über select
• Start mit Schlüsselwort go
• Gibt keine ID o.ä. zurück
50. –Rob Pike
„In programming, concurrency is the composition of
independently executing processes, while parallelism is
the simultaneous execution of (possibly related)
computations.
Concurrency is about dealing with lots of things at once.
Parallelism is about doing lots of things at once.“
52. • Einfacher Funktionsablauf im Hintergrund
• „Mach mal.“
• Dito mit Rückgabe eines Ergebnisses über einen Channel
• „Mach mal und bring mir dann das Ergebnis.“
• Kontinuierlicher Empfang zu verarbeitender Daten
• „Kümmere dich um alle meine Aufträge.“
• Dito mit serialisiertem Zugriff auf einen privaten Zustand
• „Sei mein schlauer Kollege.“
65. Aufschieben
• Funktionen können im Ablauf mit defer gestapelt werden
• Werden rückwärts beim Verlassen der umgebenden Funktion
ausgeführt
• Praktisch für Aufräumarbeiten, zum Beispiel Schließen
geöffneter Dateien
66. file, err := ioutil.TempFile("/tmp", "jax2019")
if err != nil {
return fmt.Errorf("failed to open temp file: %v", err)
}
defer file.Close()
writer := bufio.NewWriter(file)
defer writer.Flush()
writer.WriteString("JAX 2019n")
writer.WriteString("Ein Gopher im Netzn")
67. Fehlerbehandlung
• Keine Exceptions
• Fehlertyp error als letzter Rückgabewert
• Interface mit Methode Error() string
• panic() für echte Ausnahmesituationen
• Kann mit recover() aufgefangen werden
68. func CanBreakHard(x int) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v", r)
}
}()
...
if veryBadCondition {
panic("have a very, yes, very, very bad condition")
}
return nil
}
75. Fast wie Scripting
• Einfache Syntax
• Leichtgewichtiges Typenmodell
• Wenige Schlüsselworte
• Schnelle Kompilation erlaubt schnelle Tests
• Aber: Manchmal mehrere Lösungswege möglich
• Nutzung etablierter Konventionen hilft
76. Einfache Nebenläufigkeit
• Prinzipiell nur Funktionen
• Flexible Kommunikation
• Weitere Hilfen zur Synchronisation
• Aber: Kein Schutz vor gleichzeitigem Zugriff auf Variablen
• Aber: Kein Schutz vor Locks und Races
• Tools helfen, ansonsten Verantwortung des Entwicklers