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

  • 5
    いいね
  • 0
    コメント

はじめに

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)