ubuntuusers.de

ubuntuusers.deWikiGo

Go

Dieser Artikel wurde für die folgenden Ubuntu-Versionen getestet:

Hinweis:

Das gleichnamige asiatische Brettspiel ist unter Spiele/Go zu finden.

Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:

gopher.png go_logo.png Go ist eine seit 2009 von Google entwickelte Programmiersprache mit Ähnlichkeiten zu C++, Java und Erlang. Sie ist kompilierbar, nebenläufig und besitzt eine automatische Speicherbereinigung. Zur Zeit wird Go für Linux, Mac OS X und experimentell für Windows angeboten, es ist also weitestgehend plattformunabhängig. Durch die umfangreiche Standardbibliothek werden von Haus aus z.B. Netzwerkprogrammierung (TCP, HTTP), formatierte Textein/-ausgabe, Systemaufrufe etc. unterstützt.

Ende März 2012 wurde die Version 1.0 veröffentlicht {de}. Go befand sich bis dahin noch in Entwicklung, was es weiterhin schwierig macht, Tutorials oder gar Bücher zum Thema zu finden. Hilfe bieten hier die Homepage der Sprache, ein Tutorial von Miek Gieben und die Mailinglist "go-nuts". Zusätzlich liefert die vor kurzem erschienene interaktive Go-Tour eine gute Einführung (siehe Links).

Ein Aspekt, der Go von "älteren" Programmiersprachen wie C++ abhebt, ist die Verwendung des gesamten UTF-8 Zeichensatzes im Quelltext. Dies gilt sowohl für Variablennamen als auch in der Textausgabe. Somit bleiben z.B. Probleme mit Umlauten aus. Weiteres zu den Besonderheiten unter Syntax.

Experten-Info:

Auf Twitter findet man Beiträge zu Go unter dem Hashtag #golang.

Installation

Die Programmiersprache ist nicht in den offiziellen Paketquellen enthalten. Man kann aber auf ein "Personal Package Archiv" (PPA) [1] ausweichen.

PPA

Adresszeile zum Hinzufügen des PPAs:

  • ppa:gophers/go

Hinweis!

Zusätzliche Fremdquellen können das System gefährden.


Weitere Informationen bietet die Wiki/Vorlagen/PPA/ppa.png PPA-Beschreibung vom Benutzer/Team gophers.

Damit Pakete aus dem PPA genutzt werden können, müssen die Paketquellen neu eingelesen werden.

Nach dem Aktualisieren der Paketquellen kann das folgende Paket installiert [2] werden:

  • golang (ppa)

Wiki/Vorlagen/Installbutton/button.png

Darin enthalten sind Compiler, Linker und verschiedene Werkzeuge zur Formatierung des Quellcodes oder zum Nachinstallieren von Bibliotheken.

Hinweis:

Wer Go ähnlich wie Python ausprobieren möchte, kann dies im Go Playground {en} tun. Allerdings werden hier nicht alle Bibliotheken und Funktionen unterstützt.

Entwicklungswerkzeuge

Gedit

Wer sich etwas mehr Komfort bei der Quellcode-Erstellung wünscht, aber nicht gleich auf eine Entwicklungsumgebung umsteigen möchte, kann sich Gedit etwas verschönern. Gedit unterstützt zwar von Haus aus viele Sprachen, Go ist allerdings noch nicht dabei. Eine Anleitung zum nachträglichen Hinzufügen von Syntax-Highlighting ist hier {en} zu finden.

liteide.png

GolangIDE

Sucht man eine vollständige Entwicklungsumgebung, sollte man sich GolangIDE {en} ansehen, eine auf Go spezialisierte Version der Entwicklungsumgebung LiteIDE. Sie unterstützt einiges, was den Programmieralltag erleichtert:

  • Syntax-Highlighting, konfigurierbar

  • Projektmanagement

  • Gut integriertes Debugging

  • Automatische Formatierung des Quellcodes mit gofmt

  • Baumansicht von Funktionen und Variablen

  • Übersichtliche Bedienung et cetera.

Zur Zeit wird sie auf der Projektseite für Linux, Windows und Mac OS X als Download {dl} angeboten.

Hinweis:

Eventuell bekommt man beim Kompilieren eines Programms eine Fehlermeldung, da LiteIDE den Compiler im falschen Pfad sucht oder Standardbibliotheken wie "fmt" nicht findet. In dem Fall muss man im LiteIDE-Ordner unter /usr/share/liteide/environment/ die Datei linux32.env oder je nach Architektur linux64.env editieren und die enthaltenen Variablen anpassen:

1
2
3
4
GOROOT=/usr/lib/go
GOBIN=/usr/bin
GOARCH=amd64 #(oder GOARCH=386 bei 32-Bit Systemen)
GOOS=linux

Nach dem Speichern muss man in LiteIDE in der Dropdown-Liste der oberen Toolbar die editierte Datei auswählen, dann sollte es funktionieren!

Tool-Übersicht

Das Paket golang enthält viele Programme zur Go-Programmierung. Hier eine Auswahl der wichtigsten:

Tools
Befehl Bedeutung
6g / 8g Compiler, Übersicht der Argumente in der Dokumentation {en} oder bei Eingabe des Befehls ohne Parameter
6l / 8l Linker, Übersicht der Argumente s.o.
gofmt Formatiert Quellcode nach dem festgelegten Schema.
cgo Compiler für Go-Programme, die C-Code beinhalten
goinstall Befehl für die Installation von zusätzlichen Bibliotheken {en} von github etc., z.B. für Audio oder Grafik.
gomake Auf Go-Makefiles spezialisierte Variante von GNU-Make

Das erste Programm

Für den Anfang wird wie gewöhnlich nichts als der eben installierte Compiler und ein Texteditor (zum Beispiel Gedit) benötigt. Man öffnet diesen und legt die Datei first.go an:

1
2
3
4
5
6
7
8
9
//Datei first.go
/* erstes Go-Programm */
package main
import "fmt"

func main () {
    fmt.Println("Hallo golang!")
    fmt.Println("Hallo 世界!");
}

Erläuterung
Zeile Bedeutung
1+2 Kommentare, wie in C++ oder Java
3 Name des Pakets des Programms, Standard ist "main"
4 Das Paket "fmt" aus der Standardbibliothek wird eingebunden. Es stellt formatierte Textein/-ausgabe ähnlich print-/scanf zu Verfügung.
6 Hauptfunktion des Programms ohne Parameter oder Rückgabewert. Funktionen werden in Go mit dem Schlüsselwort "func" eingeleitet.
7 Die Funktion "Println" aus dem importierten Paket "fmt" wird per Punktoperator aufgerufen. Als Parameter steht hier der String "Hallo golang!". Möglich sind aber auch Variablen, Objekte oder Funktionen (mit Rückgabewert).
8 Erneut die funktion "Println", diesmal mit chinesischen Schriftzeichen. Wie bereits erwähnt, kann der gesamte UTF-8 Zeichensatz verwendet werden. Dieser Funktionsaufruf wird mit einem Semikolon abgeschlossen. Dies ist zwar wie oben nicht erforderlich, aber trotzdem möglich.
9 Die main-Funktion wird geschlossen.

Nun wird der Quelltext kompiliert:

6g -o /home/benutzer/Dokumente/first.6 /home/benutzer/Dokumente/first.go 

und gelinkt:

6l -o /home/benutzer/Dokumente/first /home/benutzer/Dokumente/first.6 

Der Compiler erstellt aus dem Quelltext first.go zunächst die Datei first.6, die dann gelinkt und somit zur ausführbaren Datei wird.

Achtung!

Der Compilername 6g setzt sich zusammen aus der x64-Architektur und "Go". Dem entsprechend muss auf 32-Bit Systemen "8g" (x86-Architektur) verwendet werden. Das Gleiche gilt für den Linker (6l / 8l).

Startet man das Programm sieht die Ausgabe so aus:

benutzer@pc-name:~$ /home/benutzer/Dokumente/first
Hallo golang!
Hallo 世界! 

Mehr zur Syntax

Go verfügt gegenüber altbewährten Programmiersprachen über einige interessante Neuerungen, oder kombiniert zumindest Vorteile einzelner Sprachen miteinander.

Variablen

In Go gibt es verschiedene Möglichkeiten, Variablen zu deklarieren und zu initialisieren:

1
2
3
4
5
6
//Beispiel 1
var txt1 string    //Deklaration
txt1 = "zugewiesen" //Initialisierung

//Beispiel 2
txt2 := txt1

Hier wird zunächst die Variable "txt1" mit dem Schlüsselwort "var" (bekannt aus JavaScript) vom Typ "string" deklariert. Auffällig ist, dass im Gegensatz zu C/C++/etc. der Typ der Variable hinter dem Namen steht. Im nächsten Schritt wird dann der Variable ein String zugewiesen.

Das zweite Beispiel arbeitet mit dem Zuweisungsoperator ":=". Dieser kombiniert die beschriebenen Schritte: er legt eine Variable "txt2" an und weist ihr den Wert von "txt1" zu. Hier muss kein Typ angegeben werden, da der Compiler diesen automatisch aus dem zugewiesenen Wert (hier string) erkennt.

Funktionen

Funktionen können in Go sehr umfangreich definiert werden:

1
2
3
func (t typ) funktionsname(q int) (r,s int) {
    return 0,0
}

Wie bereits erwähnt, wird jede Funktion mit dem Schlüsselwort "func" eingeleitet. Im folgenden wird die Syntax dieses Prototyps erläutert:

Erläuterung
Teil Optional Beschreibung
(t typ) ja Funktionen können auf einen bestimmten Typen festgelegt werden, z.B. nur Strings / TCP-Connections etc.
funktionsname nein Der Name der Funktion, über den sie später aufgerufen wird. Muss groß_ geschrieben werden, wenn die Funktion in anderen Bibliotheken nutzbar sein soll!
(q int) jein; () erforderlich Deklaration der Parameter, die der Funktion übergeben werden können
(r,s int) ja Deklaration der Rückgabewerte der Funktion. Richtig, in Go können Funktionen mehrere Werte zurückgeben! Dazu später mehr.
return 0,0 nein Return-statement, beendet die Funktion und gibt den/die Wert/Werte zurück

Beispiel 1

1
2
3
func merge(a,b string) string {
    return a+b, a, b
} 

Die Funktion "merge" akzeptiert zwei Strings als Parameter. Diese werden dann zusammengefügt und jeweils einzeln zurückgegeben. Die Funktion ist also vom Typ string und hat 3 Rückgabewerte.

Nun gibt es verschiedene Möglichkeiten, diese Funktion zu nutzen:

1
2
3
4
5
//Möglichkeit 1
add, a, b := merge("zusammen", "führen")
fmt.Println(add)
fmt.Println(a)
fmt.Println(b)

Hier werden die 3 neuen Variablen add, a und b per Zuweisungsoperator deklariert und mit den 3 Rückgabewerten der Funktion "merge" initialisiert. Die Ausgabe wäre dem entsprechend:

zusammenführen
zusammen
führen

Nun kann es z.B. bei Funktionen der Standardbibliothek vorkommen, das diese mehrere Werte zurückgeben, man allerdings nur mit einem arbeiten möchte. Würde man diese Werte allerdings beim Aufruf einfach ignorieren, gäbe es einen Compiler-Fehler. Abhilfe schafft hier die pseudo-Variable "_" (als Beispiel dient hier die oben definierte Funktion "merge"):

1
2
3
//Möglichkeit 2
add, _, _ := merge("zusammen", "führen")
fmt.Println(add)

Ausgegeben wird hier nur noch:

zusammenführen

Jetzt wird nur noch das zusammengeführte Ergebnis der Variablen "add" zugewiesen, die beiden anderen Werte werden den Pseudovariablen. Somit werden sie respektiert, aber direkt verworfen. Sinn ergibt dies zum Beispiel, wenn man bei einem Schreibvorgang nicht an der Anzahl der geschriebenen Bits interessiert ist.

Beispiel 2

1
2
3
func printStuff() {
    fmt.Println("Some stuff....")
}

Natürlich geht es auch ganz rudimentär: Diese Funktion braucht keine Parameter und gibt keine Werte zurück.

Hinweis:

Die Funktions-Syntax zu kennen, ist wichtig, um die Paketdokumentation {en} zu verstehen!

Nebenläufigkeit - Concurrency

Ein weiteres Schmankerl der neuen Programmiersprache ist die sogenannte "Nebenläufigkeit". Dieses von Erlang inspirierte Feature ermöglicht es, auf vergleichsweise einfache Weise parallel zu programmieren, eine Art Thread-Programmierung:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package main
import (
    "fmt"
    "time"
)
func wake(zeit int, grund string) {
    time.Sleep(zeit*1e9)
    fmt.Println("Zeit abgelaufen: ", grund)
}

func main() {
    go wake(180, "Tee!")
    go wake(200, "Wichtiger Termin!")
    time.Sleep(500e9)
}

Zuerst wird die Funktion "wake" definiert. Sie akzeptiert als Parameter eine Zeit (in Sekunden) und einen Grund als String. Wird sie aufgerufen, wartet sie die übergebene Zeit und gibt dann eine Meldung mit dem Grund des Aufrufs aus.

Das Entscheidende kommt erst in der main-Funktion: Die Funktion "wake" wird hier mit dem Schlüsselwort go aufgerufen. Ohne go würde die zweite wake-Funktion erst aufgerufen werden, wenn die erste beendet wird, also nach 3 Minuten. Ein go startet die Funktionen jedoch nebenläufig, also parallel. So wird man nach 3 Minuten an den Tee, und 20 Sekunden später an den wichtigen Termin erinnert.

Im Gegensatz zu diesem Beispiel ist die einfache Nebenläufigkeit z.B. bei Spielen erforderlich, wo gleichzeitig die Eingaben vom Benutzer interpretiert werden, und im Hintergrund z.B. Timer laufen.

Die Sleep-Funktion danach ist hier erforderlich, da sich sonst nach den Funktionsaufrufen das Hauptprogramm und somit auch die sog. Go-Routinen beenden würden. Professionell ist das nicht, da man meistens nicht weiß, wie lange man warten muss. Dann würde man die Routinen entweder zu früh abwürgen oder unnötig Rechenzeit verschwenden.

Diese Revision wurde am 29. März 2012 15:11 von aasche erstellt.
Die folgenden Schlagworte wurden dem Artikel zugewiesen: Programmierung

Passwort vergessen?