KDOC 415: io.Readerのシグネチャはヒープエスケープを避けられる設計になっている

この文書のステータス

  • 作成
    • 2025-07-01 貴島
  • レビュー
    • 2025-07-19 貴島

概要

io.Reader, io.Writerのインターフェース設計には、ヒープのエスケープも関係しているという。

type Reader interface {
        Read(p []byte) (n int, err error)
}

[]byte の初期化は呼び出し側の責務になっている。これによって呼び出し側がメモリ管理できるようになる。呼び出し側のスタックに留まり、ヒープにエスケープするのを抑えられる。Readを何度呼んでも新しいヒープ確保が発生しない。呼び出し側がヒープにする自由度もある。

実際に試してみる。

tmpfile=$(mktemp /tmp/tmpgo.XXXXXX.go)

cat > $tmpfile <<EOF
package main

func main() {}

// Read側で初期化して返すと、ヒープにエスケープしなければならない
func Read1() []byte {
  return make([]byte, 1)
}

// 呼び出し側で初期化してもらうようにすると、ヒープにエスケープする必要がない
func Read2([]byte) {}

EOF

go build -gcflags="-m" -o bin $tmpfile 2>&1
rm bin
rm $tmpfile
/tmp/tmpgo.s6wAwW.go:3:6: can inline main
/tmp/tmpgo.s6wAwW.go:6:6: can inline Read1
/tmp/tmpgo.s6wAwW.go:11:6: can inline Read2
/tmp/tmpgo.s6wAwW.go:7:14: make([]byte, 1) escapes to heap

関連