kurumi-bioの雑記帳

プログラミング、パソコン、写真、ペット(犬)、などなど

先週のくるみ

こんにちは、kurumi-bioです。
3月12日(日)~3月18日(土)のくるみです。

桜の花が綺麗に咲いていました

犬を飼ってみて思うこと

コマンド(コミュニケーション)
犬は、人間の2歳~3歳程度の知能で165前後の単語やジェスチャーを理解できていると言われています。 ですので、くるみに対しては命令(コマンド)という程ではないのですが、言葉で指示を出すことが多いです。 特に躾をした覚えはないのですが、理解しているので日々の生活で学んだのだと思います。

一番最初に覚えたのは、「くるみ」だと思います。自身の名前ですね。何度も呼ばれて覚えちゃいますよね。
次に覚えたのは「まて」だと思います。散歩中は必ず使う大事な言葉です。 最初は手のひらを見せて「まて」と言って覚えさせたと思います。今は「まて」だけで9割くらい止まります。 残りの1割は好奇心に負けた場合です。と言ってもトロトロと動いちゃう程度です。
それと「おいで」です。「まて」で言葉を聞く準備をさせてから「おいで」で呼び寄せる。 中型犬以上の大きさの犬の場合、犬の力が強いので、この二つの指示ができないで散歩すると犬と飼い主の両方が辛いことになると思います。

後は似たような言葉で「入っちゃダメ」「いったらダメ」「そっちはダメ」「そこまで」も理解していて、この言葉を言うと残念そうな顔でこちらを見ながら戻ってきます。
否定的な言葉だけでなく「いいよ」「こっちいこ」といった肯定的な言葉も理解していて、 公園の入り口で「はいっていいの?」と振り向いたり、道の途中で「もっと先に行っていいの?」って感じで振り向くので「いいよ」と声をかけてあげると、 尻尾を振って進んでいきます。
指示以外にも「なに嗅いでるの?」「向こうにいるのは友達かな?」「綺麗な花だね」「鴨がいるよ」と話しかけているので終始何かしら喋りながら散歩しています。
反応は有ったり無かったりですが、それでも一緒に散歩しているんだぁというのを感じられるのは、犬との散歩の楽しさだと思います。

広告の下に続きます。

先週のくるみの様子

  • 散歩
    朝の散歩は1時間半くらい。目的地に向かって歩くというよりは、フラフラと匂いを嗅いで回る感じでした。
  • 朝ご飯
    朝ご飯を食べない日は2日でした。
  • 他人
    犬友の飼い主さんでしたら触るのは無理ですが近づいても大丈夫なくらいになってきました。

先週の写真


撮影日 2023年3月12日
今回も枝をガジガジしています。


撮影日 2023年3月12日
暖かくなってきたのでシャンプーしました。短毛なので乾かすのが楽です。


撮影日 2023年3月16日
5時20分頃に撮影しました。朝焼けが綺麗です。


撮影日 2023年3月16日
自分から枝をくわえて「遊んで」と持ってきます。


撮影日 2023年3月16日
ご機嫌さんで、枝の引っ張りっこをします。


撮影日 2020年3月15日
3年前です。トライアル中の写真です。 気持ちよさそうに寝ています。鼻が短くてパピーって感じです。


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

初心者のGo言語 その27 <os.Chmodを調べる>

こんにちは、kurumi-bioです。

目次

環境

初めに

osパッケージのChmod関数は、二つ目の引数にファイルのパーミッションを渡す仕様になっている。 固定値の場合は8進数の数値を記載することが可能だが、変数で渡すときにフォーマットがわからなかったため、 プログラムを作成して調査することにした。

os.Chmodの説明は下記を参照してください。 kurumi-bio.hatenablog.com

数値とパーミッション(権限)の関係

◆テストコード

package main

import (
    "fmt"
    "os"
)

// 引数で指定したファイルのモードを引数で指定したモードに変更する
func cm(filePath string, mode int) {
    e := os.Chmod(filePath, os.FileMode(mode))
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Chmod", e))
        return
    }
    fmt.Printf("[%02d][%03o]", mode, mode)
}

// 引数で指定したファイルのモードを出力する
func pm(fileName string) {
    fi, e := os.Stat(fileName)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Stat", e))
        return
    }
    fmt.Printf("[%v]\n", fi.Mode().Perm())
}

func main() {
    const fileName = "test.txt"

    for i := 0; i < 20; i = i + 1 {
        cm(fileName, i)
        pm(fileName)
    }
}

コードの説明 os.Chmod()関数を使って"test.txt"のパーミッション(権限)を変更し、os.Stat関数を使って結果を出力します。 パーミッション(権限)に0~20までの整数を指定し、どのような値になるかを確認します。 実行時の出力は、下記の通りです。

  • 1ブロック目:os.Chmodos.FileModeに渡している数値です。
  • 2ブロック目:os.FileModeに渡している数値を8進数に変換した数値です。
  • 3ブロック目:os.Statで取得したパーミッション(権限)を出力しています。

◆実行結果(Linux)

実行結果の説明 2ブロック目の8進数の値が、Linuxのchmodコマンドの数値で指定した値と同じになっています。 ですので、数値指定の8進数を10進数に変換してos.Chmodに渡せば、 chmodコマンドと同じフォーマットでパーミッション(権限)の変更が可能になります。

8進数文字列でパーミッション(権限)を指定

◆テストコード

package main

import (
    "fmt"
    "os"
    "strconv"
)

// 引数で指定したファイルのモードを引数で指定したモードに変更する
func cm(filePath string, mode string) {
    i, _ := strconv.ParseInt(mode, 8, 32)
    e := os.Chmod(filePath, os.FileMode(i))
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Chmod", e))
        return
    }
    fmt.Printf("[%s][%03d]", mode, i)
}

// 引数で指定したファイルのモードを出力する
func pm(fileName string) {
    fi, e := os.Stat(fileName)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Stat", e))
        return
    }
    fmt.Printf("[%v]\n", fi.Mode().Perm())
}

func main() {
    const fileName = "test.txt"

    cm(fileName, "0777")
    pm(fileName)

    cm(fileName, "0700")
    pm(fileName)

    cm(fileName, "0060")
    pm(fileName)
}

コードの説明 文字列で記述されたパーミッション(権限)をstrconv.ParseInt関数を使って8進数文字列を整数(10進数)に変換してから、 os.Chmodに渡しています。

  • 1ブロック目:パーミッション(権限)に指定した8進数の文字列です。
  • 2ブロック目:整数(10進数)に変換後の値です。
  • 3ブロック目:os.Statで取得したパーミッション(権限)を出力しています。

◆実行結果(Linux)

実行結果の説明 Linuxのchmodコマンドに渡すフォーマットと同じ記載でパーミッション(権限)が変更できました。

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

メカニカルキーボード

こんにちは、kurumi-bioです。

今回は、キーボードを紹介します。 ほぼ毎日使うキーボードですが、あまり拘りがなくずーっとメンブレンキーボードを使っていました。 ただ、メーカーはLogicoolが気に入ってまして、コストパフォーマンスが良く、キータッチも好みでした。

2年くらい前だと思うのですが、某大手家電ショップでLogicoolのメカニカルキーボードを触ったときに、 「ああ、このキータッチは、初めてパソコンを使った時の感覚。懐かしく打ちやすい」ということに気づいてしまい、 それから4台のメカニカルキーボードを購入して使っています。

全部Logicoolで形もほぼ同じです。
上から

  • K835 TKL メカニカル
  • SIGNATURE K855
  • G413TKLSE メカニカル ゲーミングキーボード

です。

  • K835 TKL メカニカル
    2年前に初めて買ったメカニカルキーボードです。
    "青軸"と"赤軸"の2台持っています。
    最初、"青軸"の音とキータッチが、いかにもタイピングしてますって感じで好きだったのですが、 在宅勤務のテレビ会議で"青軸"を使うと相手の声がクリック音にかき消されてしまって、お蔵入りになってしまいました。
    "赤軸"は、会社で使っています。若干タッチ音がしますが、気にならない程度です。

  • SIGNATURE K855
    こちらは"赤軸"です。
    "K835 TKL メカニカル(青軸)"を封印したため家で使うメカニカルキーボードとして購入しました。
    このキーボードの良いところは、3台まで接続が可能なところですが、それがアダにもなっています。
    というのは、ファンクションキーのF1~F3を使って接続先を切り替えるため、
    検索で"F3"キーを使うときは、"fnキー+F3"とする必要があり、ついつい"fn"キーを押し忘れて3台目に切り替わってしまいます。 ですが、無線かつ切り替えが可能なのが大きなポイントですので、在宅勤務時の会社パソコンと家のノートパソコンで使っています。

  • G413TKLSE メカニカル ゲーミングキーボード
    タクタイルです。
    派手さは無いけど、いい仕事をする感じです。音は"赤軸"と同程度か若干静かですが、タッチ感は"赤軸"よりあるかと思います。
    SIGNATURE K855が3台切り替えられるので使うことが無いんじゃないかと思われるかもしれませんがBIOS画面用です。
    自作PCBIOS(UEFI)を設定するときにBluetoothキーボードだと設定画面が開けないため有線のキーボードが必要になり、 セール期間中に購入しました。
    ちにみに、写真ではキートップの文字がありませんが、接続すると白色に光ります。明るさは調整可能で常時消すことも可能です。

カニカルキーボードは高い印象がありますが、この3台はそこまで高くなくセールのタイミングでしたらメンブレンキーボードと変わらないくらいの値段になります。 興味がありましたら量販店で触ってみることをお勧めします。

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

初心者のGo言語 その26

こんにちは、kurumi-bioです。

目次

環境

  • 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

os.Unsetenv

func Unsetenv(key string) error

関数の説明Unsetenv は、単一の環境変数の設定を解除します。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func main() {
    e := os.Setenv("TEST", "TEST")
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Setenv", e))
        os.Exit(1)
    }
    fmt.Printf("TEST=[%s]\n", os.Getenv("TEST"))

    e = os.Unsetenv("TEST")
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Setenv", e))
        os.Exit(1)
    }
    fmt.Printf("TEST=[%s]\n", os.Getenv("TEST"))
}

コードの説明 os.Setenv()関数を使って環境変数TESTに"TEST"という値を設定し、os.Getenv()関数を使って環境変数TESTの値を出力しています。 その後、os.Unsetenv()関数を使って環境変数TESTの値を解除し、os.Getenv()関数を使って環境変数TESTの値を出力しています。

◆実行結果(Windows)

実行結果の説明

  • 1行目:環境変数TESTの値が"TEST"になりました。
  • 2行目:os.Unsetenv()関数で値を解除したので、環境変数TESTの値が空になりました。

os.UserCacheDir

func UserCacheDir() (string, error)

関数の説明 UserCacheDir は、ユーザー固有のキャッシュ データに使用する既定のルート ディレクトリを返します。ユーザーは、このサブディレクトリ内に独自のアプリケーション固有のサブディレクトリを作成し、それを使用する必要があります。
Unix システムでは、 $XDG_CACHE_HOMEが空でない場合は 指定されている値を返し、空の場合は $HOME/.cache を返します。
Darwin では、$HOME/Library/Caches を返します。
Windows では、%LocalAppData% を返します。
Plan 9 では、$home/lib/cache を返します。
場所を特定できない場合 (たとえば、$HOME が定義されていない場合)、エラーが返されます。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func us() {
    e := os.Unsetenv("XDG_CACHE_HOME")
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Unsetenv", e))
        os.Exit(1)
    }
}

func se(path string) {
    e := os.Setenv("XDG_CACHE_HOME", path)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Setenv", e))
        os.Exit(1)
    }
}

func ucd() {
    s, e := os.UserCacheDir()
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.UserCacheDir", e))
        os.Exit(1)

    }
    fmt.Printf("UserCacheDir=[%s]\n", s)
}

func main() {
    us()
    ucd()

    se("~/go/nonDir")
    ucd()
}

コードの説明 os.Unsetenv関数で環境変数XDG_CACHE_HOMEの値を解除してos.UserCacheDir()関数で返される値を出力しています。 その後、os.Setenv関数で環境変数XDG_CACHE_HOMEに値を設定してから、os.UserCacheDir()関数で返される値を出力しています。

◆実行結果(Linux)

実行結果の説明

  • 1行目:環境変数XDG_CACHE_HOMEの値が空なので、"$HOME/.cache"が出力されました。
  • 2行目:環境変数XDG_CACHE_HOMEに設定した値の"~/go/nonDir"が出力されました。

広告の下に続きます。

os.UserConfigDir

func UserConfigDir() (string, error)

関数の説明 UserConfigDir は、ユーザー固有の構成データに使用する既定のルート ディレクトリを返します。ユーザーは、このサブディレクトリ内に独自のアプリケーション固有のサブディレクトリを作成し、それを使用する必要があります。
Unix システムでは、$XDG_CONFIG_HOMEが空でない場合は 指定されている値を返し、空の場合は $HOME/.config を返します。
Darwin では、$HOME/Library/Application Support を返します。
Windows では、%AppData% を返します。
Plan 9 では、$home/lib を返します。
場所を特定できない場合 (たとえば、$HOME が定義されていない場合)、エラーが返されます。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func main() {
    fmt.Println(os.Getenv("AppData"))

    s, e := os.UserConfigDir()
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.UserConfigDir", e))
        os.Exit(1)
    }
    fmt.Println(s)
}

コードの説明 os.Getenv関数で環境変数AppDataの値を出力します。その後os.UserConfigDir関数で返される値を出力します。

◆実行結果(Windows)

実行結果の説明%AppData%と同じ値が返されることが確認できました。

os.UserHomeDir

func UserHomeDir() (string, error)

関数の説明 UserHomeDir は、現在のユーザーのホーム ディレクトリを返します。
macOS を含む Unix では、$HOME 環境変数を返します。
Windows では、%USERPROFILE% を返します。
Plan 9 では、$home 環境変数を返します。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func main() {
    s, e := os.UserHomeDir()
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.UserHomeDir", e))
        os.Exit(1)
    }
    fmt.Printf("UserHomeDir=[%s]\n", s)
}

コードの説明os.UserHomeDir関数から返ってきた値を出力します。

◆実行結果(Linux)

実行結果の説明環境変数HOMEの値が出力されました。

os.WriteFile

func WriteFile(name string, data []byte, perm FileMode) error

関数の説明 WriteFile は、指定されたファイルにデータを書き込み、必要に応じてファイルを作成します。ファイルが存在しない場合、WriteFile はパーミッション perm (umask の前) でファイルを作成します。それ以外の場合、WriteFile は、アクセス許可を変更せずに、書き込み前にファイルを切り捨てます。 Writefile を完了するには複数のシステム コールが必要なため、操作の途中で失敗すると、ファイルが部分的に書き込まれた状態のままになる可能性があります。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func pm(fileName string) {
    f, e := os.Open(fileName)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Open", e))
        os.Exit(1)
    }
    fi, se := f.Stat()
    if se != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("Stat", se))
        os.Exit(1)
    }
    fmt.Printf("%v\n", fi.Mode().Perm())
}

func rf(fileName string) {
    s, e := os.ReadFile(fileName)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.ReadFile", e))
        os.Exit(1)
    }
    fmt.Printf("[%s]\n", s)
}

func main() {
    const fileName = "writeFileTest.txt"

    os.Remove(fileName)

    e := os.WriteFile(fileName, []byte("Write Test"), 0666)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.WriteFile", e))
        os.Exit(1)
    }
    rf(fileName)
    pm(fileName)

    e = os.WriteFile(fileName, []byte("Write Test2"), 0600)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.WriteFile", e))
        os.Exit(1)
    }
    rf(fileName)
    pm(fileName)
}

コードの説明 os.WriteFile関数で"writeFileTest.txt"ファイルを作成しています。1回目と2回目でファイルに書き込む内容とファイルのパーミッションを変えています。

◆実行結果(Linux)

実行結果の説明

  • 1行目:"Write Test"という内容でファイルを新規に作成しました。
  • 2行目:ファイルのパーミッションは指定した値でした。
  • 3行目:既存ファイルの内容が"Write Test2"に上書きされていました。
  • 3行目:ファイルのパーミッションは変更されませんでした。

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

先週のくるみ

こんにちは、kurumi-bioです。
3月5日(日)~3月11日(土)のくるみです。

梅の花が綺麗に咲いていました

犬を飼ってみて思うこと

あまがみ
パピーの頃は、ほぼ毎日「あまがみ」されてた記憶があります。かなり強くかむので生傷の絶えない日々でした。
「あまがみ」は、自分だけ許していて家族は「あまがみ」をしたら叱るようにしていました。 他人嫌いな性格なので、知らない人に噛みつく心配は皆無でしたので、その点は心配していなかったです。
本によって「あまがみは𠮟るべきだ。」とも「ほおっておいても時期が来ればしなくなる。」とも書いてあり、 それなら、これもコミュニケーションの一つなんだから、とことん付き合ってみるかと叱らないでいました。
いつまでもやめない場合は、無視して部屋をでるとか、あえてグーにして噛みづらくしたりしてやめさせるようにはしました。
結局、メモを確認すると半年くらいまで「あまがみ」の記載があります。 「あまがみ」をしない間隔が、2日とか1週間、2週間と延びていき、気付いたら「あまがみ」しなくなっていて、 遅くとも1歳前には「あまがみ」をしなくなったんだと思います。
ですので、くるみは、後者の「時期がくればしなくなる」タイプだったのです。
今は、たまに甘えた感じで小刻みに"ガジガジガジ"してくるときがあります。痛く嚙むわけではなくマッサージみたいな感じです。
そのときは、こんなコミュニケーションもかわいいなぁと「あまがみ」を叱らないで正解だったなぁと思っています。

先週のくるみの様子

  • 散歩
    今週は、毎日違う行き先でした。春の匂いに誘われて色々な所に行ってるのかな。
  • 朝ご飯
    朝ご飯を食べない日が4日ありました。
  • 他人
    触れない程度に距離を取る感じです。他人は絶対ダメって感じではなくなりました。

広告の下に続きます。

先週の写真


撮影日 2023年3月5日
冒頭の梅の木の前で撮影しました。「The 犬」って感じです。


撮影日 2023年3月8日 6時13分
太陽がいい感じで出てきました。日の出の時間が早くなり、6時過ぎでも十分明るくなりました。


撮影日 2023年3月10日
雨が降っても気にせず散歩します。足が泥だらですね。


撮影日 2023年3月11日
またまた小さな枝を器用につかんで噛んでます。


撮影日 2023年3月11日
歯磨きも兼ねているので、気持ちよさそうです。


撮影日 2023年3月11日
鼻でか。暖かくなってきたので、ソファーの上でなく、床の上で休むことが多くなりました。


撮影日 2023年3月11日
目でか。


撮影日 2020年3月8日
3年前です。トライアル3日目です。 大きくなりました。


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

初心者のGo言語 その25

こんにちは、kurumi-bioです。

目次

環境

  • 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

os.Setenv

func Setenv(key, value string) error

関数の説明Setenv は、キーによって指定された環境変数の値を設定します。エラーがあれば、それを返します。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func main() {
    e := os.Setenv("TEST", "TEST")
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Setenv", e))
        return
    }
    fmt.Printf("TEST=[%s]\n", os.Getenv("TEST"))

    e = os.Setenv("TEST", fmt.Sprintf("%s;TEST2", os.Getenv("TEST")))
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Setenv", e))
        return
    }
    fmt.Printf("TEST=[%s]\n", os.Getenv("TEST"))
}

コードの説明環境変数TESTに"TEST"という値を設定しています。環境変数TESTに";TEST2"という値を追加するためos.Getenv()関数を使って既存の値を取得後fmt.Sprintf()で連結しています。

◆実行結果(Windows)

実行結果の説明

  • 1行目:環境変数TESTの値が"TEST"になりました。
  • 2行目:";TEST2"が追記されて、環境変数TESTの値が"TEST;TEST2"になりました。

os.Symlink

func Symlink(oldname, newname string) error

関数の説明 Symlink は、oldname へのシンボリック リンクとして newname を作成します。 Windows では、存在しない古い名前へのシンボリック リンクは、ファイルのシンボリック リンクを作成します。 oldname が後でディレクトリとして作成された場合、シンボリック リンクは機能しません。エラーが発生した場合、タイプは *LinkError になります。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func cf(filePath string) {
    e := os.WriteFile(filePath, []byte("Write Test"), 0666)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.WriteFile", e))
        return
    }
}

func mk(dirName string) {
    e := os.Mkdir(dirName, 0100)
    if e != nil {
        fmt.Fprintf(os.Stderr, "Error: %v \n", e)
        os.Exit(1)
    }
}

func sl(old, new string) {
    e := os.Symlink(old, new)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Symlink", e))
        return
    }
}

func main() {
    cf("linkTest")
    sl("linkTest", "linkTest-s")

    sl("non", "non-s")

    mk("testDir")
    sl("testDir", "testDir-s")
}

コードの説明cf関数でファイルを作成後に作成したファイルにシンボリックリンクを作成。存在しないファイルにシンボリックリンクを作成。存在するディレクトリにシンボリックリンクを作成を行うプログラムです。

◆実行結果(Windows)

実行結果の説明存在するファイル、存在しないファイル、存在するディレクトリの全てにシンボリックリンクが作成されました。

存在しないファイルを後から作成しても、シンボリックリンクは正常に動作しました。

存在しないリンク先を後からディレクトリ作成した場合は、シンボリックリンクは動作しませんでした。

◆実行結果(Linux)

実行結果の説明Windowsと同じで、存在するファイル、存在しないファイル、存在するディレクトリの全てにシンボリックリンクが作成されました。

存在しないファイルを後から作成しても、シンボリックリンクは正常に動作しました。この動きもWindowsと同じです。

存在しないリンク先を後からディレクトリ作成した場合も、シンボリックリンクは正常に動作しました。Windowsと異なる動きです。

広告の下に続きます。

os.TempDir

func TempDir() string

関数の説明 TempDir は、一時ファイルに使用する既定のディレクトリを返します。

Unix システムでは、空でない場合は $TMPDIR を返し、空でない場合は /tmp を返します。 Windows では、GetTempPath を使用して、%TMP%、%TEMP%、%USERPROFILE%、または Windows ディレクトリから最初の空でない値を返します。 Plan 9 では、/tmp を返します。

ディレクトリの存在は保証されておらず、アクセス許可もありません。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func main() {
    fmt.Printf("TempDir=[%s]\n", os.TempDir())
}

コードの説明 os.TempDir()関数の結果を表示するプログラムです。

◆実行結果(Windows)

実行結果の説明GetTempPath の値が表示されました。

os.Truncate

func Truncate(name string, size int64) error

関数の説明 Truncate は、指定されたファイルのサイズを変更します。ファイルがシンボリック リンクの場合、リンクのターゲットのサイズが変更されます。エラーがある場合、タイプは *PathError になります。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func ps(fileName string) {
    f, e := os.Open(fileName)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Open", e))
        return
    }
    fi, e2 := f.Stat()
    if e2 != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Stat", e))
        return
    }
    fmt.Printf("size=[%d]\n", fi.Size())
}

func sl(old, new string) {
    e := os.Symlink(old, new)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Symlink", e))
        return
    }
}

func tc(filename string, size int64) {
    e := os.Truncate(filename, size)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Truncate", e))
        return
    }
}

func main() {
    tc("truntest", 64)
    ps("truntest")

    tc("truntest", 32)
    ps("truntest")

    sl("truntest", "truntest-s")
    tc("truntest-s", 128)
    ps("truntest")
}

コードの説明存在しないファイルのファイルサイズ変更、存在するファイルのファイルサイズ変更、シンボリックファイルのファイルサイズ変更を行い、それぞれのファイルサイズを表示するプログラムです。

◆実行結果(Windows)

実行結果の説明

  • 1行目:ファイルが存在しませんでしたが、新規に64バイトでファイルが作成されました。
  • 2行目:64バイトのファイルが32バイトに変更されました。
  • 3行目:シンボリックリンクを指定しましたが、リンク元のファイルが128バイトに変更されました。

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

初心者のGo言語 その24

こんにちは、kurumi-bioです。

目次

環境

  • 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

os.Remove

func Remove(name string) error

関数の説明Remove は、指定されたファイルまたは (空の) ディレクトリを削除します。エラーがある場合、タイプは *PathError になります。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func rm(fileName string) {
    e := os.Remove(fileName)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Remove", e))
        return
    }
    fmt.Printf("[%s] Remove Success\n", fileName)
}

func main() {
    const Name = "test"
    SubPath := fmt.Sprintf("%s/sub", Name)
    rm(Name)
    os.Mkdir(Name, 0750)
    rm(Name)
    os.MkdirAll(SubPath, 0750)
    rm(Name)
    rm(SubPath)
    rm(Name)
}

コードの説明 プライベートのrm関数でos.Removeを実行しています。削除できたら"Remove Success"と出力し、失敗した場合はエラーメッセージを出力します。
この関数は、main()関数内で呼ばれており、対象ファイルが存在しなかった場合、対象フォルダが存在した場合、対象フォルダが空ではなかった場合の動きを調べるプログラムになっています。

◆実行結果(Windows)

実行結果の説明

  • 1行目:testが存在しないためThe system cannot find the file specified.(指定されたファイルが見つかりません)というエラーが出力されました。
  • 2行目:testディレクトリを作成後にos.Removeを実行しているため"Remove Success"と出力されました。
  • 3行目:test/subディレクトリを作成後にos.Removeを実行したので、"test"ディレクトリは"sub"デレクトリが存在しThe directory is not empty.(ディレクトリが空ではありません)というエラーが出力されました。
  • 4行目:"test/sub"を引数にos.Removeを実行したため、"sub"ディレクトリが空なので"Remove Success"と出力されました。
  • 5行目:4行目で"sub"ディレクトリを削除したので、testディレクトリが空ディレクトリとなり"Remove Success"と出力されました。

os.RemoveAll

func RemoveAll(path string) error

関数の説明RemoveAll は、パスとそれに含まれるすべての子を削除します。削除できるものはすべて削除しますが、最初に遭遇したエラーを返します。パスが存在しない場合、RemoveAll は nil (エラーなし) を返します。エラーがある場合、タイプは *PathError になります。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func rma(fileName string) {
    e := os.RemoveAll(fileName)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Remove", e))
        return
    }
    fmt.Printf("[%s] Remove Success\n", fileName)
}

func main() {
    const Name = "test"
    SubPath := fmt.Sprintf("%s/sub", Name)
    rma(Name)
    os.Mkdir(Name, 0750)
    rma(Name)
    os.MkdirAll(SubPath, 0750)
    rma(Name)
}

コードの説明 プライベートのrma関数でos.RemoveAllを実行しています。削除できたら"Remove Success"と出力し、失敗した場合はエラーメッセージを出力します。
この関数は、main()関数内で呼ばれており、対象ファイルが存在しなかった場合、対象フォルダが存在した場合、対象フォルダが空ではなかった場合の動きを調べるプログラムになっています。

◆実行結果(Windows)

実行結果の説明

  • 1行目:存在しないtestディレクトリを指定しos.RemoveAllを実行し"Remove Success"と出力されました。
  • 2行目:testディレクトリを作成後にos.RemoveAllを実行し"Remove Success"と出力されました。
  • 3行目:test/subディレクトリを作成後にos.RemoveAllを実行し"Remove Success"と出力されました。

広告の下に続きます。

os.Rename

func Rename(oldpath, newpath string) error

関数の説明Rename は、oldpath を newpath に名前変更 (移動) します。 newpath が既に存在し、ディレクトリでない場合、Rename はそれを置き換えます。 oldpath と newpath が異なるディレクトリにある場合、OS 固有の制限が適用される場合があります。同じディレクトリ内であっても、Unix 以外のプラットフォームでは、名前の変更はアトミック操作ではありません。エラーが発生した場合、タイプは *LinkError になります。

◆テストコード

package main

import (
    "fmt"
    "os"
)

func rf(filename string) {
    b, e := os.ReadFile(filename)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.ReadFile", e))
        return
    }
    fmt.Printf("%s [%s]\n", filename, b)
}

func rn(oldpath, newpath string) {
    e := os.Rename(oldpath, newpath)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%s\n", os.NewSyscallError("os.Rename", e))
        return
    }
    fmt.Println("Rename Success")
}

func main() {
    rn("non", "non2")
    fmt.Println("----------")

    rf("test-old")
    rn("test-old", "test-new")
    rf("test-new")
    fmt.Println("----------")

    rf("test-new2")
    rn("test-new", "test-new2")
    rf("test-new2")
    fmt.Println("----------")

    rn("test-new2", "test-dir")
    fmt.Println("----------")

    rn("test-new2", "c:\\test-new")
    rn("test-new2", "d:\\test-new")
    fmt.Println("----------")

}

コードの説明 プライベートのrn関数でos.Renameを実行しています。名前変更できたら"Rename Success"と出力し、失敗した場合はエラーメッセージを出力します。
この関数は、main()関数内で呼ばれており、元ファイル(oldpath)が存在しない場合、元ファイル(oldpath)が存在する場合、新ファイル(newpath)が存在する場合、新ファイル(newpath)がディレクトリとして存在する場合、ドライブをまたぐ場合の挙動を調べるプログラムになっています。

◆実行結果(Windows)

実行結果の説明

  • 1ブロック目:元ファイルに存在しないファイル"non"を指定してos.Renameを実行したため、The system cannot find the file specified.(指定されたファイルが見つかりません)というエラーが出力されました。
  • 2ブロック目:os.RemoveAllで"test-old"ファイルを"test-new"ファイルに名前変更に成功しtest-newファイルの中身がtest-newファイルと同じことが確認できました。
  • 3ブロック目:os.RemoveAllで"test-old"ファイルを存在する"test-new2"ファイルに名前変更(置き換え)しました。test-newファイル2の中身がtest-newファイルと同じになることが確認できました。
  • 4ブロック目:新ファイルに存在するディレクトリを指定してos.Renameを実行したため、Access is denied.(アクセスが拒否)というエラーが出力されました。
  • 5ブロック目:Dドライブに存在するファイルをCドライブのファイルを指定してos.Renameを実行したため、Access is denied.(アクセスが拒否)というエラーが出力されました。
    Dドライブは同一どらいぶなので成功して"Rename Success"が出力されました。

os.SameFile

func SameFile(fi1, fi2 FileInfo) bool

関数の説明SameFile は、fi1 と fi2 が同じファイルを記述しているかどうかを報告します。たとえば、Unix では、これは、下にある 2 つの構造体のデバイス フィールドと inode フィールドが同一であることを意味します。他のシステムでは、決定はパス名に基づく場合があります。 SameFile は、このパッケージの Stat によって返される結果にのみ適用されます。それ以外の場合は false を返します。

◆テストコード

package main

import (
    "fmt"
    "io/fs"
    "os"
)

func fi(name string) fs.FileInfo {
    fi, e := os.Stat(name)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Stat", e))
        os.Exit(1)

    }
    return fi
}

func sf(name1, name2 string) {
    fi1 := fi(name1)
    fi2 := fi(name2)

    b := os.SameFile(fi1, fi2)
    if b == true {
        fmt.Printf("[%s] = [%s]\n", name1, name2)
    } else {
        fmt.Printf("[%s] != [%s]\n", name1, name2)
    }
}

func main() {
    sf("same", "same")
    sf("same", "s-link")
    sf("same", "h-link")
    sf("same", "same1")
}

コードの説明 プライベートのsf関数でos.SameFileを実行しています。同一ファイルの場合は"="を出力し、異なる場合は"!="を出力します。
この関数は、main()関数内で呼ばれており、同一ファイル、シンボリックリンク、ハードリンク、別ファイルの挙動を調べるプログラムになっています。

◆実行結果(Windows)

実行環境の説明 s-linkファイルは、sameファイルのシンボリックリンク
h-linkファイルは、sameファイルのハードリンク
same1ファイルは、sameファイルと別ファイル
になっています。

実行結果の説明

  • 1行目:同じ名前(ファイル)を指定しos.SameFileを実行したため"="が出力されました。
  • 2行目:シンボリックファイルの名前を指定しos.SameFileを実行したため"="が出力されました。
  • 3行目:ハードリンクファイルの名前を指定しos.SameFileを実行したため"="が出力されました。
  • 4行目:異なる名前(ファイル)を指定しos.SameFileを実行したため"!="が出力されました。

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