691 Stimmen

Wie prüft man, ob eine Datei in Go existiert?

Go's Standardbibliothek hat keine Funktion, die ausschließlich dazu dient, zu prüfen, ob eine Datei existiert oder nicht (wie Python's os.path.exists ). Was ist die idiomatisch wie man es macht?

1083voto

Sridhar Ratnakumar Punkte 74723

Um zu prüfen, ob eine Datei nicht existiert, äquivalent zu Pythons if not os.path.exists(filename) :

if _, err := os.Stat("/path/to/whatever"); errors.Is(err, os.ErrNotExist) {
  // path/to/whatever does not exist
}

Um zu prüfen, ob eine Datei existiert, äquivalent zu Pythons if os.path.exists(filename) :

Bearbeitet: nach jüngsten Kommentaren

if _, err := os.Stat("/path/to/whatever"); err == nil {
  // path/to/whatever exists

} else if errors.Is(err, os.ErrNotExist) {
  // path/to/whatever does *not* exist

} else {
  // Schrodinger: file may or may not exist. See err for details.

  // Therefore, do *NOT* use !os.IsNotExist(err) to test for file existence

}

162voto

OscarRyz Punkte 189898

Antwort von Caleb Ersatz eingetragen in gonuts Mailingliste.

[...] Es wird eigentlich nicht sehr oft gebraucht und [...] mit os.Stat ist für die Fälle, in denen dies erforderlich ist, einfach genug.

[...] Ein Beispiel: Wenn Sie die Datei öffnen wollen, gibt es keinen Grund, vorher zu prüfen, ob sie existiert. Die Datei könnte zwischen der Überprüfung und dem Öffnen verschwinden, und Sie müssen sowieso die os.Open fehlerfrei. Sie rufen also einfach os.IsNotExist(err) a die Datei zu öffnen, und sich mit ihrer Nichtexistenz zu befassen (falls dies eine besondere Behandlung erfordert).

[...] Sie brauchen nicht zu prüfen, ob die Pfade überhaupt existieren (und das sollten Sie auch nicht).

  • os.MkdirAll funktioniert unabhängig davon, ob die Pfade bereits existieren oder nicht. (Außerdem müssen Sie die Fehlermeldung dieses Aufrufs überprüfen).

  • Anstelle der Verwendung von os.Create sollten Sie os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) . Auf diese Weise erhalten Sie eine Fehlermeldung, wenn die Datei bereits existiert. Auch dies hat keine Race Condition mit etwas anderem, das die Datei erstellt, im Gegensatz zu Ihrer Version, die vorher auf Existenz prüft.

Entnommen aus: https://groups.google.com/forum/#!msg/golang-nuts/Ayx-BMNdMFo/4rL8FFHr8v4J

73voto

Dave Yarwood Punkte 2517

Zunächst einmal ist zu bedenken, dass es selten vorkommt, dass Sie nur prüfen wollen, ob eine Datei existiert oder nicht. In den meisten Situationen versucht man, etwas mit der Datei zu machen, wenn sie existiert. In Go sollte jedes Mal, wenn Sie versuchen, eine Operation mit einer Datei durchzuführen, die nicht existiert, ein spezieller Fehler auftreten ( os.ErrNotExist ) und prüfen Sie am besten, ob die Rückgabe err Wert (z. B. beim Aufruf einer Funktion wie os.OpenFile(...) ) ist os.ErrNotExist .

Die empfohlene Vorgehensweise ist war früher :

file, err := os.OpenFile(...)
if os.IsNotExist(err) {
    // handle the case where the file doesn't exist
}

Allerdings, seit der Hinzufügung von errors.Is in Go 1.13 (erscheint Ende 2019), die neue Empfehlung lautet, die errors.Is :

file, err := os.OpenFile(...)
if errors.Is(err, os.ErrNotExist) {
    // handle the case where the file doesn't exist
}

In der Regel ist es am besten, die Verwendung von os.Stat um zu prüfen, ob eine Datei vorhanden ist, bevor Sie versuchen, etwas mit ihr zu tun, da es immer möglich ist, dass die Datei in dem Zeitfenster, bevor Sie etwas mit ihr tun, umbenannt, gelöscht usw. wird.

Wenn Sie jedoch mit dieser Einschränkung einverstanden sind und wirklich nur prüfen wollen, ob eine Datei existiert, ohne dann etwas Nützliches damit anzufangen (als konstruiertes Beispiel: Nehmen wir an, Sie schreiben ein sinnloses CLI-Tool, das Ihnen sagt, ob eine Datei existiert oder nicht, und sich dann beendet ¯\_()_/¯ ), dann wäre die empfohlene Vorgehensweise folgende:

if _, err := os.Stat(filename); errors.Is(err, os.ErrNotExist) {
    // file does not exist
} else {
    // file exists
}

56voto

Sie sollten die os.Stat() und os.IsNotExist() Funktionen wie im folgenden Beispiel:

func Exists(name string) (bool, error) {
    _, err := os.Stat(name)
    if err == nil {
        return true, nil
    }
    if errors.Is(err, os.ErrNotExist) {
        return false, nil
    }
    return false, err
}

edit1: Problem der Rückgabe von true unter bestimmten Umständen behoben.
edit2: umgestellt auf die Verwendung von errors.Is() von os.IsNotExist(), die viele sagen, ist ein bewährte Praktiken und hier

30voto

ZuBsPaCe Punkte 500

Was andere Antworten übersehen haben, ist, dass der Pfad, der der Funktion übergeben wird, eigentlich ein Verzeichnis sein könnte. Die folgende Funktion stellt sicher, dass der Pfad wirklich eine Datei ist.

func fileExists(filename string) bool {
    info, err := os.Stat(filename)
    if os.IsNotExist(err) {
        return false
    }
    return !info.IsDir()
}

Ein weiterer Punkt, der zu beachten ist: Dieser Code könnte immer noch zu einer Race Condition führen, bei der ein anderer Thread oder Prozess die angegebene Datei löscht oder erstellt, während die Funktion fileExists ausgeführt wird.

Wenn Sie sich darüber Sorgen machen, verwenden Sie eine Sperre in Ihren Threads, serialisieren Sie den Zugriff auf diese Funktion oder verwenden Sie ein prozessübergreifendes Semaphor, wenn mehrere Anwendungen beteiligt sind. Wenn andere Anwendungen involviert sind, die sich Ihrer Kontrolle entziehen, haben Sie wohl Pech gehabt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X