So erkennen Sie Betriebssysteme / Plattformen in Go zuverlässig

75

Folgendes verwende ich derzeit, was meiner Meinung nach die Arbeit erledigt, aber es muss einen besseren Weg geben:

func isWindows() bool {
    return os.PathSeparator == '\\' && os.PathListSeparator == ';'
}

Wie Sie sehen können, muss ich in meinem Fall nur wissen, wie man Fenster erkennt, aber ich möchte wissen, wie man Plattformen / Betriebssysteme erkennt.

Abspielen:

http://play.golang.org/p/r4lYWDJDxL

mdwhatcott
quelle
2
Aktuelle Windows-Versionen funktionieren einwandfrei mit dem Posix-Trennzeichen '/'. Sie benötigen nur einen Backslash für Bat-Skripte und alte Nicht-Posix-Versionen von Windows.
Rick-777
Können Sie "aktuell" definieren? Ich bin erst in den letzten Wochen
hartcodiert worden
2
Windows 95, 98 ME und alle früheren Versionen erfordern einen Backslash. Windows 2000, NT und höher akzeptieren Backslash und Forward Slash als Äquivalente. Backslash bietet Kompatibilität mit älteren Versionen, während Forward Slash die Posix-Konformität gewährleistet.
Rick-777
Vielen Dank für die Klarstellung @ Rick-777.
Mdwhatcott

Antworten:

141

Erkennung zur Kompilierungszeit

Wenn Sie dies tun, um je nach Betriebssystem unterschiedliche Implementierungen zu haben, ist es sinnvoller, separate Dateien mit der Implementierung dieser Funktion zu haben und jeder der Dateien Build-Tags hinzuzufügen. Dies wird an vielen Stellen in der Standardbibliothek verwendet, beispielsweise im osPaket .

Diese sogenannten "Build-Einschränkungen" oder "Build-Tags" werden hier erläutert .

Angenommen, Sie haben die Konstante PATH_SEPARATORund möchten, dass diese Plattform abhängig ist. Sie würden zwei Dateien erstellen, eine für Windows und eine für den (Unix-) Rest:

/project/path_windows.go
/project/path_unix.go

Der Code dieser Dateien wäre dann:

path_windows.go

// +build windows

package project

const PATH_SEPARATOR = '\\'

path_unix.go

// +build !windows

package project

const PATH_SEPARATOR = '/'

Sie können jetzt auf PATH_SEPARATORIhren Code zugreifen und ihn plattformabhängig machen.

Erkennung zur Laufzeit

Wenn Sie das Betriebssystem zur Laufzeit ermitteln möchten, verwenden Sie die runtime.GOOS Variable:

if runtime.GOOS == "windows" {
    fmt.Println("Hello from Windows")
}

Während dies in die Laufzeit kompiliert wird und daher die Umgebung ignoriert, können Sie dennoch relativ sicher sein, dass der Wert korrekt ist. Der Grund dafür ist, dass jede Plattform, die es wert ist, unterschieden zu werden, aufgrund unterschiedlicher ausführbarer Formate neu erstellt werden muss und somit einen neuen GOOSWert hat.

nemo
quelle
Ich habe versucht, dies auszuführen, aber ich erhalte einen seltsamen Fehler. path_windows.go: 4: 24: PATH_SEPARATOR wurde in diesem Block neu deklariert. vorherige Deklaration bei path_unix.go: 4: 24 Und ich verstehe es einfach nicht ... Bekommt der Compiler es nicht?
Ramon JA Smit
2
@ RamonJ.A.Smit Sie müssen Build-Einschränkungen zu diesen Dateien hinzufügen, wie folgt: path_unix.go sollte haben // +build !windowsund path_windows.go sollte haben // +build windows. Ich habe die Antwort oben bearbeitet, um zu zeigen, wohin sie gehen sollen. Sie müssen vor der packageAnweisung stehen und von einer Leerzeile gefolgt werden, damit sie nicht als Dokumentation für das Paket interpretiert werden.
Tim Lewis
Danke für den zusätzlichen Input! Wird damit spielen. Danke :-)
Ramon JA Smit
20

Haben Sie sich das Laufzeitpaket angesehen? Es hat eine GOOS-Konstante: http://golang.org/pkg/runtime/#pkg-constants

Tyler Egeto
quelle
2
GOOS im Laufzeitpaket wird zur Kompilierungszeit festgelegt und kann gelesen werden, ohne dass die Go-Tools installiert werden.
Tyler Egeto
2
@Matt Sie denken an die Umgebungsvariable. @ Tyler ist eine Sache, runtime.GOOSdie gut funktionieren wird, zB: play.golang.org/p/0dDIEoFXfx
Nick Craig-Wood
0

Ich bin gerade auf die Suche nach etwas anderem gestoßen und habe das Alter dieses Beitrags bemerkt, also werde ich eine aktuellere Ergänzung hinzufügen. Wenn Sie nur versuchen, den richtigen Dateipfad zu verarbeiten, würde ich filepath.Join () verwenden . Es nimmt alle Rätselraten aus OS-Problemen. Wenn Sie mehr als nur einen Dateipfad benötigen, können Sie die Laufzeitkonstanten ( runtime.GOOS& runtime.GOARCH) verwenden: Beispiel für einen Spielplatz

Bill.Caffery
quelle