Programmieren in Go

nomadsoul1, 123RF

Kurzer Prozess

Die Programmiersprache Go vereint Typsicherheit mit überschaubarer Syntax und einer umfangreichen Bibliothek. Ein kleines Tool zum Anzeigen von Prozessen demonstriert die Programmierung.
Drahtlose Netzwerke sind überall: Zu Hause, im Café und in der Firma. Im Gegensatz zu Kabelnetzen verliert der Admin bei WLANs allerdings schnell die ... (mehr)

Im November letzten Jahres feierte die Programmiersprache Go ihren vierten Geburtstag und konnte bei dieser Gelegenheit feststellen: Sie wird immer populärer. Neuestes Beispiel einer in Go geschriebenen Software ist das Container-Virtualisierungsprojekt Docker, aber auch Ubuntu schreibt das Juju-Projekt in Go neu.

Ob sich Go zur Systemprogrammierung gut eignet, ist umstritten, doch zur Beantwortung dieser Frage müsste man erst einmal klären, was man überhaupt darunter versteht. Für einen Betriebssystem-Kernel eignet sich die Sprache wohl weniger gut, auch wenn selbst dies Einzelne schon versucht haben. Abgesehen davon sind Go aber wenige Grenzen gesetzt, wenn es darum geht, Unix-Daemons, Netzwerk-Code, parallelisierte Programme und dergleichen mehr zu schreiben.

Als ausgesprochener Erbe der Programmiersprache C konzipiert (siehe [1] ), bietet es viele Möglichkeiten des Vorgängers, vereinfacht aber die Syntax und unterstützt sicheres Programmieren beispielsweise durch starke Typisierung. Über das Unsafe-Modul gleicht sich Go noch mehr an C an, aber die Sicherheit geht, wie der Modulname bereits nahelegt, verloren.

Die Standard-Library [2] von Go ist äußerst umfangreich und bietet zur Systemprogrammierung viele nützliche Module, etwa für Datenkomprimierung, Kryptografie, Binärdateiformate (ELF, Mach-O), die Arbeit mit Dateien und viele mehr. In diesem Artikel soll ein einfaches in Go geschriebenes Tool entstehen, das eine ähnliche Funktion hat wie das »ps« -Tool unter Linux.

Go-Projekte

Zunächst einmal muss man ein paar Worte über die etwas eigentümliche Verzeichnisstruktur verlieren, die für Go-Projekte vorgesehen ist. Man kann nicht einfach irgendwo seine Quellcode-Dateien ablegen und sie dann kompilieren, sondern muss einem bestimmten Schema folgen, damit das Build- und Projekttool »go« richtig funktioniert. Die Umgebungsvariable »GOPATH« legt das Verzeichnis fest, in dem sich alle Go-Projekte befinden. Darunter sind die Verzeichnisse »dist« , »bin« und »src« angesiedelt, von denen letzteres den Quellcode enthält – allerdings unterhalb weiterer Verzeichnisse, die ein Paket oder Projekt eindeutig identifizieren. Im Prinzip kann das jeder beliebige String sein, aber meistens verwendet man dafür beispielsweise die eigene Domain, gefolgt von einem Projektnamen, etwa »admin-magazin.de/Projekt« ( Abbildung 1 ). Das Tool »go« lädt auch Projekte aus dem Internet, etwa von Github, die dann in »$GOPATH/src/github.com/Projekt« landen.

Abbildung 1: Die Struktur von Go-Projekten: ein Toplevel-Directory, darunter Verzeichnisse für Binärdateien und Quellcode-Projekte.

Im Beispiel sollen die Projekte in »$HOME/gocode« liegen. Die Umgebungsvariable dafür setzt »export GOPATH=$HOME/gocode« . Der folgende Aufruf legt das Projektverzeichnis für das noch zu programmierende Tool »lap« (List All Processes) an:

mkdir -p src/admin-magazin.de/lap

Wer hier nun ein kleines Hello-World-File ablegt (siehe [1] ), kann das Projekt folgendermaßen kompilieren:

go build admin-magazin.de/lap

Bei einem Blick in die Datei »GOPATH/bin« wird man aber feststellen, dass dort keine Datei liegt. Dorthin kopiert »go« das Binary nämlich nur mit dem »install« -Befehl, den man am besten gleich statt »build« verwendet. Programmbibliotheken landen in »GOPATH/pkg« . Die Object Files lassen sich per »go clean Package« wieder entfernen, mit einem zusätzlichen Schalter entfernt »go clean -f« auch die Binaries wieder.

Die Idee hinter »lap« ist recht simpel. Unter Linux findet sich im Proc-Dateisystem »/proc« für jeden laufenden Prozess ein virtuelles Verzeichnis mit der Prozess-ID als Name. Darunter befinden sich eine ganze Reihe virtueller Dateien mit Informationen zu diesem Prozess, darunter die Dateien »stat« und »status« , die etwa die Parent-Prozess-ID, den Eigentümer, die Startzeit und so weiter enthalten.

Dateien verarbeiten

Die erste Aufgabe besteht also darin, die Dateien in »/proc« aufzulisten und diejenigen mit den Prozessinfos herauszufiltern. Sie lässt sich recht einfach mit der Funktion »filepath.Glob« erledigen, die alle Dateinamen in einem Array zurückgibt, die auf ein bestimmtes Muster passen. Der folgende Ansatz geht einen kleinen Umweg, um ein paar Aspekte von Schleifen und String-Verarbeitung in Go zu demonstrieren.

Den Inhalt eines Verzeichnisses liefert ein Aufruf der Funktion »ReadDir« im »ioutils« -Paket. Um die Einträge alle durchzugehen, verwendet man die For-Schleife mit einer Range-Expression, mit der man über Arrays, Slices, Strings, Maps und Channels iteriert. Mit nur einer Laufvariable weist »range« dieser den Array-Index zu. Einer zweiten Variablen weist Go automatisch den Inhalt des entsprechenden Array-Elements zu.

entries, err := ioutil.ReadDir(procDir)
for index, proc := range entries {
    // do something with proc
}

Das akzeptiert der Go-Compiler nur, wenn man mit der Variable »index« auch etwas anfängt. Will man das nicht, kann man stattdessen auch den Go-Platzhalter für Variablen »_« verwenden. Ein »proc« ist im Beispiel vom Typ »os.FileInfo« , der ein Interface implementiert, das unter anderem den Aufruf »Name()« einschließt, um den Dateinamen auszulesen.

Ähnliche Artikel

comments powered by Disqus
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Ausgabe /2023