Skip to content

Go Programmiersprache Cheat Sheet

Go (auch bekannt unter Golang) ist eine statisch typisierte, kompilierte Sprache, die von Robert Griesemer, Rob Pike und Ken Thompson bei Google entwickelt wurde. Die Go-Syntax ähnelt C, bietet jedoch Funktionen wie Speichersicherheit, GC (Garbage Collection), strukturelle Typisierung und CSP-style Nebenläufigkeit.

Hello world

package main

import "fmt"

func main() {
  message := greetMe("world")
  fmt.Println(message)
}

func greetMe(name string) (string) {
  return "Hello, " + name + "!"
}
$ go build

Variablen

Variablendeklaration

var msg string
msg = "Hello"

Kurzschreibweise

msg := "Hello"

Konstanten

const Phi = 1.618

Konstanten können Zeichen, Zeichenfolgen, boolesche Werte oder numerische Werte sein.

Basistypen

Strings

str := "Hello"
str := `Mehrzeilige
Zeichenfolge`

Der Typ für Zeichenfolgen ist string.

Zahlen

Typische Typen

num := 3          // int
num := 3.         // float64
num := 3 + 4i     // complex128
num := byte('a')  // byte (Alias für uint8)

Andere Typen

var u uint = 7        // uint (vorzeichenlos)
var p float32 = 22.7  // 32-bit float

Pointer

func main () {
  b := *getPointer()
  fmt.Println("Wert ist", b)
}
 
func getPointer () (myPointer *int) {
  a := 234
  return &a
}

Pointer zeigen auf einen Speicherort einer Variablen. Go verwendet Garbage Collection.

Arrays

// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}

Arrays haben eine feste Größe.

Slices

slice := []int{2, 3, 4}
slice := []byte("Hello")

Im Gegensatz zu Arrays haben Slices eine dynamische Größe.

Kontrollstrukturen

Bedingungen

if day == "sunday" || day == "saturday" {
  rest()
} else if day == "monday" && isTired() {
  groan()
} else {
  work()
}

Anweisung in if

if _, err := getResult(); err != nil {
  fmt.Println("Uh oh")
}

Eine if-Anweisung kann eine einfache Anweisung vor dem Bedingungsausdruck ausführen.

Switch

switch day {
  case "sunday":
    // cases "fallen" standardmäßig nicht durch!
    fallthrough

  case "saturday":
    rest()

  default:
    work()
}

Funktionen

Lambdas

myfunc := func() bool {
  return x > 10000
}

Funktionen sind „First-Class-Objekte“.

Mehrere Rückgabetypen

a, b := getMessage()
func getMessage() (a string, b string) {
  return "Hello", "World"
}

Benannte Rückgabewerte

func split(sum int) (x, y int) {
  x := sum * 4 / 9
  y := sum - x
  return
}

Durch Benennung der Rückgabewerte in der Deklaration gibt return (ohne Argumente) die Variablen mit diesen Namen zurück.

Pakete

Laden

import "fmt"
import "math/rand"
import (
  "fmt"        // gibt fmt.Println
  "math/rand"  // gibt rand.Intn
)

Beides ist gleich.

Aliase

import r "math/rand"
 
r.Intn()

Exportierte Namen

func Hello () {
  ···
}

Exportierte Namen beginnen mit einem Großbuchstaben.

Packages

package hello

Jede Paketdatei muss mit einer package-Anweisung beginnen.

Nebenläufigkeit (Concurrency)

Goroutines

func main() {
  // Ein "Channel"
  ch := make(chan string)

  // Starte nebenläufige Routinen
  go push("Moe", ch)
  go push("Larry", ch)
  go push("Curly", ch)

  // Lese 3 Ergebnisse
  // (Da unsere Goroutinen nebenläufig sind,
  // ist die Reihenfolge nicht garantiert!)
  fmt.Println(<-ch, <-ch, <-ch)
}
 
func push(name string, ch chan string) {
  msg := "Hey, " + name
  ch <- msg
}

Channels sind nebenläufigkeitssichere Kommunikationsobjekte, die in Goroutinen verwendet werden.

Puffer-Channels

ch := make(chan int, 2)
ch <- 1
ch <- 2
ch <- 3
// fatal error:
// all goroutines are asleep - deadlock!

Puffer-Channels begrenzen die Anzahl der Nachrichten, die sie halten können.

Channels schließen

Schließt einen Channel

ch <- 1
ch <- 2
ch <- 3
close(ch)

Über einen Channel iterieren, bis er geschlossen ist

for i := range ch {
  ···
}

Geschlossen, wenn ok == false

v, ok := <- ch

Defer & Panic

Defer

func main() {
  defer fmt.Println("Fertig")
  fmt.Println("Arbeite...")
}

Verzögert die Ausführung einer Funktion, bis die umgebende Funktion zurückkehrt. Die Argumente werden sofort ausgewertet, aber der Funktionsaufruf wird erst am Ende ausgeführt.

Defer mit Lambdas

func main() {
  defer func() {
    fmt.Println("Fertig")
  }()
  fmt.Println("Arbeite...")
}

Lambdas eignen sich besser für verzögerte Blöcke.

Strukturen (Structs)

Definition

type Vertex struct {
  X int
  Y int
}

func main() {
  v := Vertex{1, 2}
  v.X = 4
  fmt.Println(v.X, v.Y)
}

Literale

v := Vertex{X: 1, Y: 2}
// Feldnamen können weggelassen werden
v := Vertex{1, 2}
// Y ist implizit
v := Vertex{X: 1}

Sie können auch Feldnamen angeben.

Pointer auf Strukturen

v := &Vertex{1, 2}
v.X = 2

Wenn v ein Pointer ist, ist v.X das Gleiche wie (*v).X.

Methoden

Receiver

type Vertex struct {
  X, Y float64
}
func (v Vertex) Abs() float64 {
  return math.Sqrt(v.X * v.X + v.Y * v.Y)
}
 
v := Vertex{1, 2}
v.Abs()

Es gibt keine Klassen, aber Sie können Funktionen für Typen mittels Receivern definieren.

Pointer-Receiver

func (v *Vertex) Scale(f float64) {
  v.X = v.X * f
  v.Y = v.Y * f
}
 
v := Vertex{6, 12}
v.Scale(0.5)
// `v` wird aktualisiert