はじめに
こんにちわ、すえけん(@sueken5)です。
今回の記事ではgolangのioインターフェースを使うと効果的な処理がかけるようになるのでそれを紹介します。
io.Reader/io.Writer
io.Reader/io.Writerはioパッケージで提供されているインターフェースです。
どこで使われているかというとbyte列をいじる際によく採用されています。よくみるところだとencoding/json
やos
パッケージのファイル周りで使われています。
Benchmark
次の二つの関数のベンチマークを測ってみます。一つはreaderからbyteを取り出した後にmarshalし、もう一つはdecoderにFileインスタンスを渡しています。
package io_bench
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
type test struct {
Message string `json:"message"`
}
//not use io interface.
func Ex1() error {
f, err := os.Open("test.json")
if err != nil {
return fmt.Errorf("ex1 err: %w", err)
}
defer f.Close()
data, err := ioutil.ReadAll(f)
if err != nil {
return fmt.Errorf("ex1 err: %w", err)
}
t := &test{}
if err := json.Unmarshal(data, t); err != nil {
return fmt.Errorf("ex1 err: %w", err)
}
return nil
}
//use io interface.
func Ex2() error {
f, err := os.Open("test.json")
if err != nil {
return fmt.Errorf("ex2 err: %w", err)
}
defer f.Close()
t := &test{}
if err := json.NewDecoder(f).Decode(t); err != nil {
return fmt.Errorf("ex1 err: %w", err)
}
return nil
}
結果は次の通りです。(ベンチマーク用のテストコードはこちら)
> go test -bench . -benchmem
goos: darwin
goarch: amd64
pkg: github.com/sueken5/io-bench
BenchmarkEx1-8 88365 12195 ns/op 2392 B/op 10 allocs/op
BenchmarkEx2-8 1000000000 0.000065 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/sueken5/io-bench 1.224s
decoderにFileインスタンスを渡してる方が圧倒時に早くメモリ効率も良いです。
まとめ
通信のレスポンスなどをこのようにioインターフェースをうまく使うことができればよりパフォーマンスのでるプログラムが書けそうです。