kurumi-bioの雑記帳

プログラミング、パソコン、ペット、 犬、お出かけ

初心者のGo言語 -20- <IsExist,IsNotExist,IsPathSeparator,IsPermission,IsTimeout,Lchown>

こんにちは、kurumi-bioです。 第6回目のosパッケージ(標準ライブラリー)の学習です。

環境

  • Windows
    OSバージョン:Windows11 Home 22H2
    Go言語のバージョン:go version go1.20 windows/amd64

  • Linux
    OSバージョン:openSUSE Leap 15.4
    Go言語のバージョン:go version go1.20.1 linux/amd64

IsExist関数

func IsExist(err error) bool

IsExist は、ファイルまたはディレクトリが既に存在することを報告するためにエラーが認識されているかどうかを示すブール値を返します。 ErrExist といくつかの syscall エラーによって満たされます。 この関数は、errors.Is よりも前から存在します。 os パッケージによって返されるエラーのみをサポートします。新しいコードでは、errors.Is(err, fs.ErrExist) を使用する必要があります。

<サンプルコード>IsExistSample.go

package main

import (
    "fmt"
    "os"
)

func main() {
    e := os.Mkdir("isExistTest", 0750)
    if e != nil {
        fmt.Fprintf(os.Stderr, "os.Mkdir Error: %v\n", e)
        if os.IsExist(e) == true {
            fmt.Println("true")
        } else {
            fmt.Println("false")
        }
    } else {
        fmt.Println("success")
    }
}

os.Mkdir関数を使ってディレクトリを作成します。もし、エラーが発生した場合はエラー原因が既にディレクトリが存在するかの結果を返します。

<実行結果>

2回連続で実行すると、既に同名ディレクトリが存在するのでエラー(error)になります。 そのエラー(error)をos.IsExist(e)の引数に渡すとtrueが返ってきましたので、ディレクトリが存在しないためエラーになったことがわかりました。

IsNotExist関数

func IsNotExist(err error) bool

IsNotExist は、ファイルまたはディレクトリが存在しないことを報告するためにエラーが認識されているかどうかを示すブール値を返します。これは、ErrNotExist といくつかのシステムコール エラーによって満たされます。 この関数は、errors.Is よりも前から存在します。 os パッケージによって返されるエラーのみをサポートします。新しいコードでは、errors.Is(err, fs.ErrNotExist) を使用する必要があります。

<サンプルコード>IsNotExistSample.go

package main

import (
    "fmt"
    "os"
)

func main() {
    e := os.Remove("isExistTest")
    if e != nil {
        fmt.Fprintf(os.Stderr, "Remove Error: %v\n", e)
        if os.IsNotExist(e) == true {
            fmt.Println("true")
        } else {
            fmt.Println("false")
        }
    } else {
        fmt.Println("success")
    }
}

os.Remove関数を使ってディレクトリを削除します。もし、エラーが発生した場合はエラー原因が対象ディレクトリが存在しないかの結果を返します。

<実行結果>

IsExistSample.goで作成したディレクトリを削除します。2回連続で実行すると1回目でディレクトリを削除するので2回目はエラーになります。
そのエラー(error)をos.IsNotExistの引数に渡すとtrueが返ってきましたので、ディレクトリが存在しないためエラーになったことがわかりました。

では、ディレクトリが存在する場合は、falseが返ってくるのか試してみます。

IsExistSample.goを実行しディレクトリを作成します。
作成したディレクトリにtest.txtというファイルを作成します。
IsNotExistSampleを実行すると、指定したディレクトリが空でなかったためos.Removeがエラーを返します。
そのエラー(error)をos.IsNotExistの引数に渡すとfalseが返ってきましたので、ディレクトリが存在するのでエラーになったことがわかりました。

IsPathSeparator関数

func IsPathSeparator(c uint8) bool

IsPathSeparator は、c がディレクトリ区切り文字かどうかを報告します。

<サンプルコード>IsPathSeparatorSample.go

package main

import (
    "fmt"
    "os"
)

func main() {
    b := os.IsPathSeparator('/')
    fmt.Print("/=")
    if b == true {
        fmt.Println("true")
    } else {
        fmt.Println("false")
    }

    fmt.Print("\\=")
    b = os.IsPathSeparator('\\')
    if b == true {
        fmt.Println("true")
    } else {
        fmt.Println("false")
    }

    fmt.Print(":=")
    b = os.IsPathSeparator(':')
    if b == true {
        fmt.Println("true")
    } else {
        fmt.Println("false")
    }
}

/\:が、ディレクトリ区切り文字かを返すプログラムです。

<実行結果>

上がWindowsで、下がLinuxの結果です。
Windowsでは/\がセパレータとして使えますが、Linux/のみセパレータとして使用可能です。

<広告の下に記事が続きます。>

IsPermission関数

func IsPermission(err error) bool

IsPermission は、アクセス許可が拒否されたことを報告するエラーが既知であるかどうかを示すブール値を返します。これは、ErrPermission といくつかの syscall エラーによって満たされます。 この関数は、errors.Is よりも前から存在します。 os パッケージによって返されるエラーのみをサポートします。新しいコードでは、errors.Is(err, fs.ErrPermission) を使用する必要があります。

<サンプルコード>IsPermissionSample.go

package main

import (
    "fmt"
    "os"
)

func main() {
    _, e := os.ReadFile("test")
    if e != nil {
        fmt.Printf("err=%v\n",e)
        b := os.IsPermission(e)
        if b == true {
            fmt.Println("IsPermission: true")
        } else {
            fmt.Println("IsPermission: false")
        }
        if os.IsExist(e) == true {
            fmt.Println("IsExist: true")
        } else {
            fmt.Println("IsExist: false")
        }
    }
}

os.ReadFile関数を使ってファイルを読み込みます。もし、エラーが発生した場合はエラー原因がアクセス許可が拒否されたかを返します。

<実行結果>

Linuxで実行しました。Read権を落としていますのでos.ReadFileがエラーを返します。 そのエラー(error)をos.IsPermission()の引数に渡すとtrueが返ってきましたので、アクセス許可が拒否されたのでエラーになったことがわかりました。 ファイルが存在するのにos.IsExist関数がfalseを返したのは不明です。

IsTimeout関数

func IsTimeout(err error) bool

IsTimeout は、タイムアウトが発生したことを報告するエラーが既知であるかどうかを示すブール値を返します。 この関数は errors.Is よりも前のものであり、エラーがタイムアウトを示しているかどうかの概念があいまいになる可能性があります。たとえば、Unix エラー EWOULDBLOCK は、タイムアウトを示す場合と示さない場合があります。新しいコードでは、os.ErrDeadlineExceeded など、エラーを返す呼び出しに適した値を持つ errors.Is を使用する必要があります。

<サンプルコード>IsTimeoutSample.go

package main

import (
    "fmt"
    "os"
)

func main() {
    _, e := os.ReadFile("test")
    if e != nil {
        fmt.Printf("err=%v\n", e)
        b := os.IsTimeout(e)
        if b == true {
            fmt.Println("true")
        } else {
            fmt.Println("false")
        }
    }
}

os.ReadFile関数を使ってファイルを読み込みます。もし、エラーが発生した場合はエラー原因がタイムアウトが発生したかを返します。

<実行結果>

エラー原因がタイムアウトではなかったのでfalseが返ってきました。

Lchown関数

func Lchown(name string, uid, gid int) error

Lchown は、指定されたファイルの数値 uid と gid を変更します。ファイルがシンボリック リンクの場合、リンク自体の uid と gid が変更されます。エラーがある場合、タイプは PathError になります。 Windows では、PathError でラップされた syscall.EWINDOWS エラーが常に返されます。

<サンプルコード>LchownSample.go

package main

import (
    "fmt"
    "os"
)

func main() {
    e := os.Lchown("LchownTest", 1002, 1001)
    if e != nil {
        fmt.Fprintf(os.Stderr, "os.Lchown Error: %v \n", e)
        os.Exit(1)
    } else {
        fmt.Println("success")
    }
}

LchownTestファイルのuidを1002、gidを1001に変更します。 予め1002のuidと1001のgidを作成しておく必要があります。

<実行結果>

上がWindowsで下がLinuxです。 Windowsは、サポートされていないためエラー終了しました。 Linuxは、指定したuidとgidに変更されました。

最後までご覧いただきありがとうございます