Posted on

[Golang]Goのio/ioutilパッケージは分かりやすくて使いやすい

Goのioパッケージは主にインターフェースになっていて他のパッケージで多く実装されています。またioパッケージにもパブリックな関数がありファイルの入出力はできますが少し細かい処理になります。io/ioutilパッケージを使うとファイルの入出力処理が簡単にできます。以下にio/ioutilパッケージを使った処理とそれに対するテストコードを記載します。

io/ioutil/ioutil.go

ReadAll()

func ReadAll() string {
    file, _ := os.Open("testdata/src.txt")
    b, _ := ioutil.ReadAll(file)
    return string(b)
}

ReadAllテスト

func TestReadAll(t *testing.T) {
    str := ReadAll()
    if str != "0123456789" {
        t.Errorf("TestReadAll Error. %s", str)
    }
}

ReadFile()

func ReadFile() string {
    b, _ := ioutil.ReadFile("testdata/src.txt")
    return string(b)
}

ReadFileテスト

func TestReadFile(t *testing.T) {
    str := ReadFile()
    if str != "0123456789" {
        t.Errorf("TestReadAll Error. %s", str)
    }
}

WriteFile()

func WriteFile() string {
    b := []byte("0123456789")
    _ = ioutil.WriteFile("testdata/dst.txt", b, os.ModePerm)
    b, _ = ioutil.ReadFile("testdata/dst.txt")
    return string(b)
}

WriteFileテスト

func TestWriteFile(t *testing.T) {
    str := WriteFile()
    if str != "0123456789" {
        t.Errorf("TestReadAll Error. %s", str)
    }
}

ReadDir()

func ReadDir() []os.FileInfo {
    fileInfo, _ := ioutil.ReadDir("testdata")
    return fileInfo
}

ReadDirテスト

func TestReadDir(t *testing.T) {
    fileInfoList := ReadDir()
    for _, fileInfo := range fileInfoList {
        if !(fileInfo.Name() == "src.txt" || fileInfo.Name() == "dst.txt") {
            t.Errorf("TestReadDir Error. %s", fileInfo.Name())
        }
    }
}

NopCloser Close()

NopCloserreaderインターフェースしかなく、closerを持っていない場合にダミーでcloserインターフェースを追加することができます。NopCloserClose()は何もしません。

func NopCloserClose() error {
    reader := bytes.NewBufferString("test")
    readCloser := ioutil.NopCloser(reader)
    return readCloser.Close()
}

NopCloser Closeテスト

func TestNopCloserClose(t *testing.T) {
    if NopCloserClose() != nil {
        t.Errorf("TestNopCloserClose Error. %v", NopCloserClose())
    }
}

DevNull Write()

DevNullを使うと吐き捨て用のWriterを利用することができます。Writeの他にもWriteStringReadFrom関数が用意されているのですが、今の所Writeしか呼び出すことができません(叩き方がわかりません)。これについては気になったのでWriteStringReadFromも叩けるようにGo本体にコードを変更してコントリビュートしてみたのですが、あえなくNGをくらいました。有り難いことに金曜日夕方にリクエストして夜には返信が来たのでレスポンスは早かったです。

Sorry, but we don’t want new public API here.
The type doesn’t need to be exported in order to implement WriteString, etc.
https://go-review.googlesource.com/c/go/+/203377
func DevNullWrite() int {
    writer := ioutil.Discard
    n, _ := writer.Write(make([]byte, 1024))
    return n
}

DevNull Writeテスト

func TestDevNullWrite(t *testing.T) {
    if DevNullWrite() != 1024 {
        t.Errorf("TestDevNullWrite Error. %v", DevNullWrite())
    }
}

Go本体へコントリビュートするにはGerritを使う必要があるのですが、本家のドキュメントがしっかりしているのと、日本語でも「Go にコントリビュートするまでの手順」という記事を公開してくれているので比較的すんなり行うことができました。

Contribution Guide

The Go project welcomes all contributors. This document is a guide to help you through the process of contributing to the Go project, which is a little different from that used by other open source projects. We assume you have a basic understanding of Git and Go.

Go にコントリビュートするまでの手順 – blog.syfm

最近、ついに Go ( golang/go) にコントリビュートしました! 正確にはレビュー中で、レビューが通ってもマージされるのは Go 1.10 なので、だいぶ先は長いですが取り敢えず自分のできることは一通り終わりました。 Go ではレビューシステムに GitHub は使っておらず、代わりに Google が開発した Gerrit を使っています。 普段の GitHub を利用したフローと結構異なっていたので備忘録がてらブログに書いておこうと思います。

io/ioutil/tempfile.go

TempFile()

func TempFile() *os.File {
    f , _ := ioutil.TempFile("testdata/tempfile", "test")
    return f
}

TempFileテスト

func TestTempFile(t *testing.T) {
    f := TempFile()
    if f.Name() == "" {
        t.Errorf("TestTempFile error %s", f.Name())
    }
    defer os.RemoveAll("testdata/tempfile")
}

TempDir()

func TempDir() string {
    name, _ := ioutil.TempDir("testdata", "test")
    return name
}

TempDirテスト

func TestTempDir(t *testing.T) {
    name := TempDir()
    if name == "" {
        t.Errorf("TestTempDir error %s", name)
    }
    fileInfoList, _ := ioutil.ReadDir("testdata")
    for _, fileInfo := range fileInfoList {
        if fileInfo.IsDir() {
            os.RemoveAll("testdata/" + fileInfo.Name())
        }
    }
}

ソースコード

taisa831/sandbox-go

You can’t perform that action at this time. You signed in with another tab or window. You signed out in another tab or window. Reload to refresh your session. Reload to refresh your session.

参考書籍

本書はGoio.Writerio.Readerからはじまりシステムの深いところまで丁寧に説明されているのでとてもおすすめです。Webで無料で見れますし書籍版、PDF版で購入も可能です。

Web版

Goならわかるシステムプログラミング

書籍版