golangのioutilべしべし叩いてみた

More than 1 year has passed since last update.


はじめに

ioutilの公開されてる関数ベシベシ叩いてみた記録。

エラー処理についての記載はノイズになるので、書きませぬ。


TempDir(dir, prefix string) (name string, err error)

第一引数(dir)を指定しないとテンポラリ領域にディレクトリを作成する。

TempDirって書いてあったから、シャットダウンフック的な何かがディレクトリ消すかと思ったけどそんなことなかった。

dir, _ := ioutil.TempDir("", "beroringa")

fmt.Println(dir)
defer os.RemoveAll(dir)


result

/tmp/user/1000/beroringa627495697



面白かったとこ

これ。

r = r*1664525 + 1013904223 // constants from Numerical Recipes

何してんのか良く解んなかったから調べてみたら、擬似乱数生成のプログラムに記載があった。


ioutil/tempfile.go

func nextSuffix() string {

randmu.Lock()
r := rand
if r == 0 {
r = reseed()
}
r = r*1664525 + 1013904223 // constants from Numerical Recipes
rand = r
randmu.Unlock()
return strconv.Itoa(int(1e9 + r%1e9))[1:]
}


TempFile(dir, prefix string) (f *os.File, err error)

ioutil.TempDirと同じで、第一引数(dir)を指定しないとテンポラリ領域にファイルを作成する。

こっちもシャットダウンフック的な何かがファイルを消すことはない。

fp, _ := ioutil.TempFile("", "xxx")

fpath := fp.Name()
fmt.Println(fpath)
defer fp.Close()


result

/tmp/user/1000/xxx422381226



WriteFile(filename string, data []byte, perm os.FileMode) error

ファイル名と権限を指定してファイルに指定データを書き込む。

ioutil.WriteFile(fpath, []byte("write!!\n"), 0644)


ReadAll(r io.Reader) ([]byte, error)

バッファリングしながらデータ終端までデータを読み込む。

contents, _ := ioutil.ReadAll(strings.NewReader("ベンサォン"))

fmt.Printf("%q\n", contents)


result

"ベンサォン"



面白かったとこ

panicの捕まえ方。

panic起きてもdeferは呼ばれるから、deferの中でrecover呼んでエラーハンドリングするみたい。

PanicAndRecoverに色々書いてある。後で読も。


ioutil.go

func readall(r io.reader, capacity int64) (b []byte, err error) {

buf := bytes.newbuffer(make([]byte, 0, capacity))
// if the buffer overflows, we will get bytes.errtoolarge.
// return that as an error. any other panic remains.
defer func() {
e := recover()
if e == nil {
return
}
if panicerr, ok := e.(error); ok && panicerr == bytes.errtoolarge {
err = panicerr
} else {
panic(e)
}
}()
_, err = buf.readfrom(r)
return buf.bytes(), err
}


ReadFile(filename string) ([]byte, error)

ファイルパスを指定してファイルを読み込む。

内部的にはos.Open呼んでファイルのポインタをioutil.ReadAllの呼び先に渡す感じになってる。

// $ cat /tmp/yakiniku.txt

// $ 焼肉たべたい
contents, _ = ioutil.ReadFile("/tmp/yakiniku.txt")


result

焼肉たべたい



ReadDir(dirname string) ([]os.FileInfo, error)

指定ディレクトリ配下のファイルからソート済みのファイルリストを取得する。

files, _ := ioutil.ReadDir("/tmp")

for _, file := range files {
fmt.Println(file.Name())
}


result

tmp1

tmp2
...


NopCloser(r io.Reader) io.ReadCloser

なにもしないCloserくっつけてReaderCloser作る。

c := ioutil.NopCloser(string.NewReader("キャベツ太郎"))

fmt.Printf("Close() is %v.\n", c.Close())


result

Close() is <nil>.



ioutil.Discard

書き捨てWriter

n, _ = ioutil.Discard.Write([]byte("gomipoyo"))

fmt.Printf("write size is %v byte.\n", n)


result

write size is 8 byte.



面白かったとこ

blackHoleに飲み込まれる感。


ioutil.go

var blackHolePool = sync.Pool{

New: func() interface{} {
b := make([]byte, 8192)
return &b
},
}

func (devNull) ReadFrom(r io.Reader) (n int64, err error) {
bufp := blackHolePool.Get().(*[]byte)
readSize := 0
for {
readSize, err = r.Read(*bufp)
n += int64(readSize)
if err != nil {
blackHolePool.Put(bufp)
if err == io.EOF {
return n, nil
}
return
}
}
}

// Discard is an io.Writer on which all Write calls succeed
// without doing anything.
var Discard io.Writer = devNull(0)