Skip to content

Instantly share code, notes, and snippets.

@josephvusich
Forked from mastef/isexist_vs_isnotexist.go
Created March 14, 2021 20:13
Show Gist options
  • Save josephvusich/9f89ca88e10f76c0ea73fd2c9378617c to your computer and use it in GitHub Desktop.
Save josephvusich/9f89ca88e10f76c0ea73fd2c9378617c to your computer and use it in GitHub Desktop.

Revisions

  1. @mastef mastef created this gist Feb 4, 2016.
    107 changes: 107 additions & 0 deletions isexist_vs_isnotexist.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,107 @@
    /*
    Watch out, os.IsExist(err) != !os.IsNotExist(err)
    They are error checkers, so use them only when err != nil, and you want to handle
    specific errors in a different way!
    Their main purpose is to wrap around OS error messages for you, so you don't have to test
    for Windows/Unix/Mobile/other OS error messages for "file exists/directory exists" and
    "file does not exist/directory does not exist"
    This way you can handle such an error, while still failing on other unexpected errors like "permission denied",
    "filesystem error", "wrong filename" error, etc.
    */

    // We want to create a symlink, but the target path exists already :

    if _, err := os.Symlink("/old/path", "/path/to/whatever"); os.IsExist(err) {
    // error happened, can't Symlink
    // can't create symlink because /path/to/whatever already exists
    }

    // We want to stat a file, but it doesn't exist :

    if _, err := os.Stat("/path/to/whatever"); os.IsNotExist(err) {
    // error happened, can't Stat!
    // /path/to/whatever does not exist
    }

    // BUT :

    // Anti-pattern : We want to stat a file, and continue if it exists :

    if _, err := os.Stat("/file/that/exists"); os.IsExist(err) {
    // will never trigger!

    // why? because os.Stat runs normally if file exists.
    // it's expected behaviour for os.Stat, so it doesn't throw an error

    // os.IsExist() does not receive an error ( it's nil ), so it can't tell you
    // if the error message was "file not found"
    }

    // Instead :
    // We want to stat a file, and continue if it exists :

    _, err := os.Stat("/file/that/exists");

    if err != nil {
    if os.IsNotExist(err) {
    // file does not exist, do something
    } else {
    // more serious errors
    }
    }

    // file exists.. continue with code here, or in else statement, or specify if err == nil { // do something }


    /*
    os.IsExist(err) is good for cases when you expect the file to not exist yet,
    but the file actually exists :
    */

    os.Symlink("/path/that/exists", "/path/to/symlink/target")
    // os.IsExist(err) will trigger when target exists already

    os.Mkdir(target)
    // os.IsExist(err) will trigger because target path already exists

    os.OpenFile(target, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
    // os.IsExist(err) will trigger when target exists because O_EXCL means that file should not exist yet

    /*
    os.IsNotExist(err) is good for more common cases where you expect the file to exists,
    but it actually doesn't exist :
    */

    os.Chdir()
    os.Stat()
    os.Open()
    os.OpenFile() // without os.O_EXCL
    os.Chmod()
    os.Chown()
    os.Close()
    os.Read()
    os.ReadAt()
    os.ReadDir()
    os.Readdirnames()
    os.Seek()
    os.Truncate()
    os.Write()
    os.WriteAt()
    os.WriteString()
    // etc...

    // More reading :

    // http://stackoverflow.com/a/12518877
    // http://stackoverflow.com/questions/25939584/file-both-exists-and-not-exists-in-go/25939743#25939743
    //
    // https://github.com/golang/go/search?utf8=%E2%9C%93&q=IsExist
    // https://golang.org/pkg/os/#IsExist
    //
    // http://stackoverflow.com/search?q=os.IsExist
    // http://stackoverflow.com/search?q=os.IsNotExist