
Go ist eine kompilierbare, statisch typisierte und prozedurale Programmiersprache. Zu einem gewissen Grad unterstützt Go objektorientierte, funktionale und aspektorientierte Programmierung. Die Sprache ist ursprünglich 2007 von Robert Griesemer, Rob Pike und Ken Thompson bei Google entworfen worden. Der Öffentlichkeit bekannt gemacht wurde Go 2009. Die erste stabile Version erschien 2012.
Alleinstellungsmerkmale
Nach eigener Aussage der Entwickler ist Go aus Unzufriedenheit mit den bei Google verwendeten Sprachen wie Java, C und C++ entworfen worden. Nicht nur erschienen diese zu komplex, sie adressierten die aktuellen Herausforderungen wie Parallelisierung, Skalierbarkeit und praktikable Speicherverwaltung bei gleichzeitig hoher Geschwindigkeit nicht angemessen genug.
Go geht diese Probleme an, indem es auf viele Abstraktionsmöglichkeiten verzichtet, Nebenläufigkeiten tief in der Sprache verankert und eine automatische Speicherbereinigung bietet.
Einsatzbereiche
Go ist primär für die Entwicklung systemnaher serverseitiger Software konzipiert. Go wird bei Google intensiv eingesetzt. Wenig überraschend ist Go auch im Kubernetes-Ökosystem weit verbreitet. Grundsätzlich ist Go im Cloud-Umfeld gut vertreten. Kubernetes selbst und Helm sind in Go geschrieben, ebenso Docker, Prometheus, Grafana, OpenShift und die Hashicorp-Produkte Terraform, Vault, Nomad und Consul. Eine umfangreiche Liste der Unternehmen, die intern Go einsetzen, ist am Ende des Blogbeitrags verlinkt. Unter anderem beinhaltet sie 1Password, Alibaba, Allegro, Atlassian, Baidu, ByteDance, Delivery Hero, Limango, Oppo, Orange, OwnCloud, Posteo, Sixt, SoundCloud, Trivago, Walmart, Xiaomi und Zalando.
Pros
Go ist aufgrund der gut lesbaren, minimalistischen Syntax leicht zu erlernen. Da Go im Gegensatz zu Sprachen wie Ruby bewusst auf Flexibilität verzichtet, ist Go-Code oft auch leicht zu lesen. Neben diesen Eigenschaften tragen auch der eigene Garbage Collector, die statische Typisierung und das Fehlen von Generics dazu bei, dass das Fehlerrisiko in Go geringer ist als in Sprachen wie z.B. C, Java oder Python.
Go bietet eine solide Standardbibliothek an und verspricht mit dem Go 1 compatibility promise in zukünftigen Versionen möglichst abwärtskompatibel zu bleiben. Mit Google im Rücken und der Popularität bei Google selbst und im Cloud-Umfeld kann man davon ausgehen, dass Go langfristig bestehen bleibt und weiter entwickelt wird.
Die größte Stärke von Go meiner Meinung nach ist die native Unterstützung für Nebenläufigkeiten. In Go werden nebenläufige Prozesse über das vorangesetzte Schlüsselwort go
gestartet. Zwischen diesen so genannten Goroutinen (und dem Hauptprogramm) kann über Channels kommuniziert werden. Channels erlauben den Austausch von Informationen in eine oder beide Richtungen und können auch als Broadcast eingesetzt werden, etwa um allen Goroutinen mitzuteilen, dass sich das Hauptprogramm in wenigen Augenblicken beenden wird.
Der nachfolgende Code gibt die Quadrate der Zahlen 1 bis 10 in einer Goroutine aus. Die Zahlen 1 bis 10 werden dabei über einen Channel in
transportiert. Nachdem das Hauptprogramm den Channel in
geschlossen hat, gibt die Goroutine den String done aus und signalisiert dem Hauptprogramm danach über das Schließen eines zweiten Channels out
, dass sie durchgelaufen ist. Nachdem das Hauptprogramm erfolgreich aus dem Channel out
gelesen hat, gibt es really done aus. Da Channels blockierend arbeiten, ist damit garantiert, dass das Programm immer gleich abläuft. Ohne den Channel out
würde sich das Programm beenden, sobald das letzte Statement der Funktion main
abgearbeitet ist, da das Hauptprogramm nicht auf noch laufende Goroutinen wartet.
package main
import ("fmt")
func printSquares(in chan int, out chan int) {
for {
number := <- in
if number != 0 {
fmt.Print(number*number, "\n")
} else { break }
}
fmt.Print("done", "\n")
close(out)
}
func main() {
in := make(chan int)
out := make(chan int)
go printSquares(in, out)
for i := 1; i <= 10; i++ {
in <- i
}
close(in)
<- out
fmt.Print("really done", "\n")
}
Ein weiterer interessanter Mechanismus ist das Schlüsselwort defer
. Es wird einem Befehl vorangestellt und sorgt dafür, dass dieser Befehl ganz am Ende der Funktion aufgerufen wird. Es entspricht damit in etwa dem finally
-Block in Sprachen wie Java, C# und Python, unterscheidet sich aber in der Art und Weise, wie es aufgerufen wird. Eine Go-Funktion kann eine beliebige Anzahl an defer
-Statements haben, die auf einen Stack gelegt und nach Ablauf des restlichen Codes in umgekehrter Reihenfolge abgearbeitet werden. Versetzt man also drei Print-Statements 1, 2 und 3 mit dem defer
-Statement, so werden diese am Ende der Funktion in der Reihenfolge 3, 2, 1 ausgegeben. defer
wird üblicherweise für Aufräumarbeiten wie dem Schließen von Ressourcen verwendet.
Cons
Go ist eine verhältnismäßig junge Sprache und hat noch kein so großes Ökosystem an Drittanbieterbibliotheken erschaffen, wie andere Sprachen, die in den 1990er Jahren entstanden sind. Damit ist auch die Zukunft der Sprache ungewisser als für andere Sprachen wie Java oder Python. Zwar verspricht Google möglichst abwärtskompatibel zu bleiben, ob das so bleibt und wie die Verbreitung von Go in zehn Jahren aussieht, vermag aber noch niemand abzuschätzen.
Go hat eine Reihe bewusst geschaffener Eigenschaften, für die sich ein Entwickler entweder begeistern oder ihnen gegenüber komplett abweisend aufstellen kann. Meine persönliche Meinung ist daher im höchsten Maße subjektiv und in jedem Fall lohnt es sich genau hinzuschauen, was man mit der Sprache machen möchte, um zu entscheiden, ob sie für diese Zwecke geeignet ist oder eher nicht.
Go unterstützt keine Vererbung, Objektorientierung lässt sich nur eingeschränkt über Structs mit Funktionen und Mixins realisieren. Interfaces in Go sind implizit, was bedeutet, dass Go nicht zur Kompilierzeit, sondern erst zur Laufzeit feststellen kann ob ein Objekt ein Interface implementiert oder nicht, wobei letzteres dann zu einem Fehler führt. Zum jetzigen Zeitpunkt fehlen in Go auch Enums und Generics und es gibt keinen Ternary-Operator. Zwar verstehe ich die Intention der Entwickler hinter diesen Entscheidungen bzw. Prioritäten (zur Umsetzung von Generics gibt es mittlerweile einen Vorschlag), jedoch fehlen mir damit die Abstraktionsmöglichkeiten um große komplexe Systeme mit einer Domäne gut strukturieren zu können, was für mich die Einsatzzwecke von Go stark einschränkt.
Eine weitere Designentscheidung, die mir nicht sehr zusagt, ist der Umgang mit Fehlern. In Go gibt es kein Konzept von Exceptions, stattdessen ist der zweite Rückgabewert einer Funktion in der Regel der Fehlercode, der im Erfolgsfall den Wert nil
hat. Das führt allerdings auch dazu, dass man nicht einfach einen größeren Code-Block mit einem Try-Catch kapseln kann, sondern jedes relevante Statement einzeln auf Fehler untersuchen muss. Auch wenn man sich eine generische Funktion baut, die den Rückgabewert aller solchen Statements zentral ausliest und behandelt, wird das meiner Meinung nach am Ende nicht so übersichtlich wie ein Catch-Block.
Datenblatt
Name | Go |
Webseite | https://golang.org |
Erscheinungsjahr | 2009 |
Aktuellste Version (Stand 14. März 2021) | Version 1.15.9 vom 10. März 2021 |
Typisierung | statisch |
Paradigmen | imperativ prozedural objektorientiert funktional aspektorientiert |
Pros | Cons |
---|---|
gute Zukunftsperspektiven durch Weiterentwicklung bei Google und dem Versprechen, nach Möglichkeit abwärtskompatibel zu bleiben | relativ junge Sprache |
leicht zu erlernen | viele Abstraktionsmöglichkeiten fehlen (Vererbung, explizite Interfaces, Generics, Enums) |
gut lesbare Syntax | kein Ternary Operator |
geringes Fehlerrisiko bei der Entwicklung | die C-ähnliche Fehlerbehandlung wird nicht jedem gefallen |
Nebenläufigkeiten als nativer Bestandteil der Sprache | |
„defer“ ist ein interessantes und mächtiges Schlüsselwort | |
virtuallet
virtuallet ist ein kleines Programm von mir, welches ich in diversen Programmiersprachen implementiert habe. Hier geht es direkt zum Go-Code von virtuallet auf GitLab. Hier gibt es weitere Infos zu virtuallet.
- Blogartikel von Rob Pike zur Entstehung von Go - Liste mit Unternehmen, die intern Go einsetzen - Vorschlag zur Umsetzung von Generics in Go