kurumi-bioの雑記帳

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

初心者のGo言語 -23- <NewSyscallError,Pipe,ReadFile,Readlink>

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

第9回目の**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

NewSyscallError関数

func NewSyscallError(syscall string, err error) error

関数の説明 NewSyscallError は、指定されたシステム コール名とエラーの詳細を含む新しい SyscallError をエラーとして返します。便宜上、err が nilの場合、NewSyscallError は nil を返します。

 

◆テストコード

package main

import (
	"errors"
	"fmt"
	"os"
)

func main() {
	e := os.NewSyscallError("Syscall", errors.New("Error"))
	fmt.Fprintf(os.Stderr, "%v\n", e)
}    
コードの説明 引数は、システムコール名とエラー詳細ですので、素直に"Syscall"と"Error"を渡して結果を確認します。

 

◆実行結果(Windows)

実行結果の説明 引数に渡した"Syscall"とErrorの間に":"が追加されました。
Go言語の流儀だと思いますので、システムコールでエラーメッセージを表示するときはos.NewSyscallErrorを使うようにしたいと思います。

Pipe関数

func Pipe() (r *File, w *File, err error)

関数の説明 パイプは、接続されたファイルのペアを返します。 r から読み取り、w に書き込まれたバイトを返します。ファイルとエラーがあればそれを返します。

 

◆テストコード

package main

import (
	"fmt"
	"os"
)

func main() {
	var s string
	r, w, _ := os.Pipe()

	fmt.Fprint(w, "aaa")
	w.Close()

	fmt.Fscan(r, &s)
	fmt.Printf("%s\n", s)
}    
コードの説明 wに"aaa"を書き込んで、rから読み取った情報を出力するプログラムです

 

◆実行結果(Windows)

実行結果の説明 変数rを読み込んで表示すると、変数wに書き込んだ値"aaa"が表示されました。

**広告の下に続きます。**

ReadFile関数

func ReadFile(name string) ([]byte, error)

関数の説明 ReadFile は、指定されたファイルを読み取り、内容を返します。呼び出しが成功すると、err == EOF ではなく、err == nil が返されます。 ReadFile はファイル全体を読み取るため、Read からの EOF を報告するエラーとして扱いません。

 

◆テストコード

package main

import (
	"fmt"
	"os"
)

func read(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\n", b)
}

func main() {
	read("test.txt")
	read("non.txt")
} 
ソースの説明 存在するファイルと存在しないファイルを指定した場合の動作を確認したかったので、 ファイル名を引数としたread関数を作成しました。
関数内でos.ReadFileを実行しています。
最初は存在するファイル(test.txt)を引数に渡して、次に存在しないファイル(non.txt)を引数に渡して、 動作を確認します。

 

◆実行結果(Windows)

実行結果の説明
  • "test.txt"を引数としてos.ReadFile関数を実行するとファイルの中身が出力されました。
  • 存在しないファイル"non.txt"を引数としてos.ReadFile関数を実行するとThe system cannot find the file specified(ファイルが見つからなかった)というエラーが発生しました。
エラーメッセージをos.NewSyscallError関数で作成していますので、メッセージの先頭に"os.ReadFile:"が出力されています。

ReadFile関数

func Readlink(name string) (string, error)

関数の説明 readlink は、指定されたシンボリック リンクの宛先を返します。エラーがある場合、タイプは *PathError になります。

 

◆テストコード

package main

import (
	"fmt"
	"os"
)

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

func main() {
	rl("symboliclink.txt")
	rl("hardlink.txt")
}    
ソースの説明 シンボリックリンクとハードリンクを引数に渡したときの結果を表示するプログラムです。今回も内部でos.Readlink関数を呼ぶ関数を作成しています。

 

◆実行結果(Windows)

実行結果の説明 シンボリックリンク(symboliclink.txt)はリンク先のファイル(test.txt)が表示されました。
ハードリンク(hardlink.txt)は、The file or directory is not a reparse point. (リパースポイント?ではない)というエラーが発生しました。

 

◆実行結果(Linux)

実行結果の説明 ハードリンクを引数にするとエラーになるのはWindowsと同じ挙動ですが、エラーメッセージがinvalid argument(無効な引数)というエラーメッセージになりました。Windowsのエラーメッセージよりわかりやすいかなと思いました。

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