[インデックス 18903] ファイルの概要
このコミットは、Go言語の標準ライブラリであるbytes
パッケージとstrings
パッケージにおけるReader
型のReadAt
メソッドの挙動に関する修正です。具体的には、ReadAt
メソッドがレシーバ(Reader
のインスタンス)を予期せず変更(mutate)しないように、以前の変更を部分的に元に戻すものです。これにより、ReadAt
がレシーバをミューテートしないことを前提としていたテストにおけるデータ競合の問題が解決されました。
コミット
commit cc4bdf0226f192432a0d7c95b02cf3ecced81c15
Author: Rui Ueyama <ruiu@google.com>
Date: Wed Mar 19 12:13:47 2014 -0700
strings, bytes: ReadAt should not mutate receiver
CL 77580046 caused a data race issue with tests that assumes ReadAt
does not mutate receiver. This patch partially revert CL 77580046
to fix it.
LGTM=bradfitz
R=golang-codereviews, bradfitz
CC=golang-codereviews
https://golang.org/cl/77900043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/cc4bdf0226f192432a0d7c95b02cf3ecced81c15
元コミット内容
このコミットは、以前の変更であるCL 77580046
によって導入された問題を修正するために、その変更を部分的に元に戻すものです。CL 77580046
の具体的な内容は、このコミットメッセージからは直接読み取れませんが、ReadAt
メソッドがレシーバをミューテートするような変更を含んでいたと推測されます。
このコミットでは、以下の4つのファイルから合計4行の削除が行われています。
src/pkg/bytes/reader.go
:ReadAt
メソッドからr.prevRune = -1
の行を削除。src/pkg/bytes/reader_test.go
:UnreadRuneErrorTests
から"ReadAt"
に関連するテストケースを削除。src/pkg/strings/reader.go
:ReadAt
メソッドからr.prevRune = -1
の行を削除。src/pkg/strings/strings_test.go
:UnreadRuneErrorTests
から"ReadAt"
に関連するテストケースを削除。
変更の背景
変更の背景には、CL 77580046
という以前のコミットが深く関わっています。このCL 77580046
によって、bytes.Reader
とstrings.Reader
のReadAt
メソッドにr.prevRune = -1
という行が追加されました。この行は、ReadAt
が呼び出された際に、Reader
の内部状態であるprevRune
(直前に読み込んだルーンに関する情報)をリセットする役割を持っていました。
しかし、ReadAt
メソッドは通常、ランダムアクセス読み取りを行うためのものであり、ストリームの現在位置や直前のルーンといった内部状態を変更すべきではありません。なぜなら、ReadAt
は複数のゴルーチンから同時に呼び出される可能性があるため、内部状態を変更するとデータ競合(data race)が発生するリスクがあるからです。
このCL 77580046
の変更により、ReadAt
がレシーバをミューテートしないことを前提としていた既存のテストでデータ競合が発生するようになりました。このコミットは、そのデータ競合を修正するために、CL 77580046
で追加されたr.prevRune = -1
の行を削除し、ReadAt
メソッドがレシーバをミューテートしない元の挙動に戻すことを目的としています。
前提知識の解説
Go言語のio.Reader
とio.ReaderAt
インターフェース
Go言語では、データの読み取り操作を抽象化するためにio.Reader
とio.ReaderAt
という重要なインターフェースが定義されています。
-
io.Reader
:type Reader interface { Read(p []byte) (n int, err error) }
Read
メソッドは、データをストリームから読み取り、p
に書き込みます。読み取り操作は通常、ストリームの現在位置を進めます。これはシーケンシャルな読み取りに適しています。 -
io.ReaderAt
:type ReaderAt interface { ReadAt(p []byte, off int64) (n int, err error) }
ReadAt
メソッドは、指定されたオフセットoff
からデータを読み取り、p
に書き込みます。ReadAt
の重要な特性は、ストリームの現在位置を変更しないことです。これにより、複数のゴルーチンが同時に異なるオフセットからデータを読み取ることが可能になり、並行処理において非常に有用です。ファイルやメモリ上のデータなど、ランダムアクセスが可能なデータソースに対して実装されます。
bytes.Reader
とstrings.Reader
Goの標準ライブラリには、バイトスライスや文字列をio.Reader
インターフェースとして扱うための具体的な実装が提供されています。
bytes.Reader
:[]byte
(バイトスライス)を読み取り可能なストリームとして扱います。strings.Reader
:string
(文字列)を読み取り可能なストリームとして扱います。
これらのReader
型は、内部に読み取り位置や、場合によっては直前に読み込んだルーン(Unicodeコードポイント)に関する情報(prevRune
など)を保持しています。
データ競合 (Data Race)
データ競合は、複数のゴルーチンが同時に同じメモリ位置にアクセスし、少なくとも1つのアクセスが書き込みであり、かつそれらのアクセスが同期メカニズムによって順序付けされていない場合に発生するプログラミング上のバグです。データ競合が発生すると、プログラムの動作が予測不能になったり、クラッシュしたりする可能性があります。
ReadAt
メソッドは、その性質上、並行して呼び出されることが想定されるため、内部状態をミューテート(変更)するとデータ競合のリスクが高まります。
r.prevRune = -1
の意味
r.prevRune
は、bytes.Reader
やstrings.Reader
が内部的に保持するフィールドで、UnreadRune
メソッド(直前に読み込んだルーンをストリームに戻す)をサポートするために、直前に読み込んだルーンの情報を格納します。-1
は、有効なルーンが読み込まれていない状態を示すことが多いです。
ReadAt
メソッド内でr.prevRune = -1
と設定することは、ReadAt
が呼び出された際に、UnreadRune
の内部状態をリセットすることを意味します。しかし、前述の通り、ReadAt
はストリームの現在位置やその他の内部状態を変更すべきではないため、この操作はReadAt
のセマンティクスに反し、並行処理における問題を引き起こす可能性がありました。
技術的詳細
このコミットの技術的な核心は、io.ReaderAt
インターフェースのセマンティクスを厳密に遵守することにあります。io.ReaderAt
のドキュメントには、「ReadAt
は、基礎となる入力ストリームのオフセットを変更しない」と明記されています。この「オフセット」は、単に読み取り位置だけでなく、Reader
が持つ他の内部状態(例えばprevRune
)にも適用されるべきであるという解釈が、この修正の根底にあります。
CL 77580046
では、bytes.Reader
とstrings.Reader
のReadAt
メソッドに以下の行が追加されました。
r.prevRune = -1
この変更は、ReadAt
が呼び出された際に、Reader
のprevRune
フィールドを-1
にリセットすることを意味します。prevRune
は、UnreadRune
メソッドが正しく機能するために、直前に読み込まれたルーンの情報を保持する内部状態です。
しかし、ReadAt
はランダムアクセスを目的としたメソッドであり、ストリームの現在位置やUnreadRune
の状態のような内部状態を変更すべきではありません。もし複数のゴルーチンが同時にReadAt
を呼び出し、その中でr.prevRune
が変更されると、UnreadRune
を使用する他の操作(例えば、同じReader
インスタンスに対してRead
やUnreadRune
を呼び出すゴルーチン)との間でデータ競合が発生する可能性がありました。特に、ReadAt
がprevRune
をリセットすることで、UnreadRune
が期待する値を見つけられなくなり、テストが失敗する原因となりました。
このコミットでは、CL 77580046
で追加されたr.prevRune = -1
の行を削除することで、ReadAt
メソッドがReader
の内部状態を一切変更しないように修正しています。これにより、ReadAt
の呼び出しが副作用を持たなくなり、並行処理環境下での安全性が確保されます。
また、テストファイル(reader_test.go
とstrings_test.go
)からReadAt
に関連するテストケースが削除されているのは、おそらくUnreadRuneErrorTests
というテストスイートが、ReadAt
がprevRune
をリセットするという誤った前提に基づいて設計されていたためと考えられます。ReadAt
がprevRune
をリセットしないように修正されたため、その前提に基づくテストは不要になったか、あるいは不適切になったため削除されたと推測されます。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更は、以下の2つのファイルにおけるReadAt
メソッドからの1行の削除です。
-
src/pkg/bytes/reader.go
--- a/src/pkg/bytes/reader.go +++ b/src/pkg/bytes/reader.go @@ -43,7 +43,6 @@ func (r *Reader) Read(b []byte) (n int, err error) { } func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) { - r.prevRune = -1 if off < 0 { return 0, errors.New("bytes: invalid offset") }
-
src/pkg/strings/reader.go
--- a/src/pkg/strings/reader.go +++ b/src/pkg/strings/reader.go @@ -42,7 +42,6 @@ func (r *Reader) Read(b []byte) (n int, err error) { } func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) { - r.prevRune = -1 if off < 0 { return 0, errors.New("strings: invalid offset") }
また、関連するテストファイルからもReadAt
に関するテストケースが削除されています。
-
src/pkg/bytes/reader_test.go
--- a/src/pkg/bytes/reader_test.go +++ b/src/pkg/bytes/reader_test.go @@ -138,7 +138,6 @@ var UnreadRuneErrorTests = []struct { f func(*Reader) }{ {"Read", func(r *Reader) { r.Read([]byte{}) }}, - {"ReadAt", func(r *Reader) { r.ReadAt([]byte{}, 0) }}, {"ReadByte", func(r *Reader) { r.ReadByte() }}, {"UnreadRune", func(r *Reader) { r.UnreadRune() }}, {"Seek", func(r *Reader) { r.Seek(0, 1) }},
-
src/pkg/strings/strings_test.go
--- a/src/pkg/strings/strings_test.go +++ b/src/pkg/strings/strings_test.go @@ -863,7 +863,6 @@ var UnreadRuneErrorTests = []struct { f func(*Reader) }{ {"Read", func(r *Reader) { r.Read([]byte{}) }}, - {"ReadAt", func(r *Reader) { r.ReadAt([]byte{}, 0) }}, {"ReadByte", func(r *Reader) { r.ReadByte() }}, {"UnreadRune", func(r *Reader) { r.UnreadRune() }}, {"Seek", func(r *Reader) { r.Seek(0, 1) }},
コアとなるコードの解説
このコミットの核心は、ReadAt
メソッドが「レシーバをミューテートしない」というio.ReaderAt
インターフェースの重要な契約を再確立することです。
bytes.Reader
とstrings.Reader
のReadAt
メソッドからr.prevRune = -1
という行が削除されたことで、ReadAt
の呼び出しはReader
インスタンスのprevRune
フィールドに影響を与えなくなりました。これにより、以下の重要な点が保証されます。
- 副作用の排除:
ReadAt
は、データの読み取り以外の副作用(この場合は内部状態の変更)を持たなくなります。これは、関数型プログラミングの原則にも通じる、より予測可能で安全なコードの実現に貢献します。 - 並行処理の安全性向上: 複数のゴルーチンが同じ
Reader
インスタンスに対して同時にReadAt
を呼び出しても、prevRune
フィールドを巡るデータ競合が発生しなくなります。ReadAt
はオフセット指定によるランダムアクセスを意図しているため、並行アクセスされることが多く、この変更は並行処理の堅牢性を高めます。 io.ReaderAt
セマンティクスの遵守:io.ReaderAt
インターフェースのドキュメントに明記されている「基礎となる入力ストリームのオフセットを変更しない」という契約を、より広範な意味で遵守することになります。これは、単に読み取り位置だけでなく、UnreadRune
のような他の操作に影響を与える可能性のある内部状態も変更しないことを意味します。
テストファイルからのReadAt
関連のテストケースの削除は、ReadAt
がprevRune
をリセットするという誤った前提に基づいていたテストが、この修正によって不要になったか、あるいは不適切になったためと考えられます。ReadAt
がprevRune
をリセットしないという正しい挙動になったため、その挙動を期待するテストはもはや意味をなさなくなった、と解釈できます。
この修正は、Go言語の標準ライブラリが提供するインターフェースのセマンティクスを厳密に守り、並行処理における潜在的なバグを未然に防ぐための重要なステップと言えます。
関連リンク
- Go言語の
io
パッケージドキュメント: https://pkg.go.dev/io - Go言語の
bytes
パッケージドキュメント: https://pkg.go.dev/bytes - Go言語の
strings
パッケージドキュメント: https://pkg.go.dev/strings - Go言語におけるデータ競合の検出 (Go Race Detector): https://go.dev/doc/articles/race_detector
参考にした情報源リンク
- Go言語の公式ドキュメント
- Go言語のソースコード
- Go言語の
io.ReaderAt
インターフェースに関する一般的な解説 - データ競合に関する一般的なプログラミングの知識
- Go言語のコードレビューシステム (Gerrit) のCL (Change List) の概念
[インデックス 18903] ファイルの概要
このコミットは、Go言語の標準ライブラリであるbytes
パッケージとstrings
パッケージにおけるReader
型のReadAt
メソッドの挙動に関する修正です。具体的には、ReadAt
メソッドがレシーバ(Reader
のインスタンス)を予期せず変更(mutate)しないように、以前の変更を部分的に元に戻すものです。これにより、ReadAt
がレシーバをミューテートしないことを前提としていたテストにおけるデータ競合の問題が解決されました。
コミット
commit cc4bdf0226f192432a0d7c95b02cf3ecced81c15
Author: Rui Ueyama <ruiu@google.com>
Date: Wed Mar 19 12:13:47 2014 -0700
strings, bytes: ReadAt should not mutate receiver
CL 77580046 caused a data race issue with tests that assumes ReadAt
does not mutate receiver. This patch partially revert CL 77580046
to fix it.
LGTM=bradfitz
R=golang-codereviews, bradfitz
CC=golang-codereviews
https://golang.org/cl/77900043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/cc4bdf0226f192432a0d7c95b02cf3ecced81c15
元コミット内容
このコミットは、以前の変更であるCL 77580046
によって導入された問題を修正するために、その変更を部分的に元に戻すものです。CL 77580046
の具体的な内容は、このコミットメッセージからは直接読み取れませんが、ReadAt
メソッドがレシーバをミューテートするような変更を含んでいたと推測されます。
このコミットでは、以下の4つのファイルから合計4行の削除が行われています。
src/pkg/bytes/reader.go
:ReadAt
メソッドからr.prevRune = -1
の行を削除。src/pkg/bytes/reader_test.go
:UnreadRuneErrorTests
から"ReadAt"
に関連するテストケースを削除。src/pkg/strings/reader.go
:ReadAt
メソッドからr.prevRune = -1
の行を削除。src/pkg/strings/strings_test.go
:UnreadRuneErrorTests
から"ReadAt"
に関連するテストケースを削除。
変更の背景
変更の背景には、CL 77580046
という以前のコミットが深く関わっています。このCL 77580046
によって、bytes.Reader
とstrings.Reader
のReadAt
メソッドにr.prevRune = -1
という行が追加されました。この行は、ReadAt
が呼び出された際に、Reader
の内部状態であるprevRune
(直前に読み込んだルーンに関する情報)をリセットする役割を持っていました。
しかし、ReadAt
メソッドは通常、ランダムアクセス読み取りを行うためのものであり、ストリームの現在位置や直前のルーンといった内部状態を変更すべきではありません。なぜなら、ReadAt
は複数のゴルーチンから同時に呼び出される可能性があるため、内部状態を変更するとデータ競合(data race)が発生するリスクがあるからです。
このCL 77580046
の変更により、ReadAt
がレシーバをミューテートしないことを前提としていた既存のテストでデータ競合が発生するようになりました。このコミットは、そのデータ競合を修正するために、CL 77580046
で追加されたr.prevRune = -1
の行を削除し、ReadAt
メソッドがレシーバをミューテートしない元の挙動に戻すことを目的としています。
前提知識の解説
Go言語のio.Reader
とio.ReaderAt
インターフェース
Go言語では、データの読み取り操作を抽象化するためにio.Reader
とio.ReaderAt
という重要なインターフェースが定義されています。
-
io.Reader
:type Reader interface { Read(p []byte) (n int, err error) }
Read
メソッドは、データをストリームから読み取り、p
に書き込みます。読み取り操作は通常、ストリームの現在位置を進めます。これはシーケンシャルな読み取りに適しています。 -
io.ReaderAt
:type ReaderAt interface { ReadAt(p []byte, off int64) (n int, err error) }
ReadAt
メソッドは、指定されたオフセットoff
からデータを読み取り、p
に書き込みます。ReadAt
の重要な特性は、ストリームの現在位置を変更しないことです。これにより、複数のゴルーチンが同時に異なるオフセットからデータを読み取ることが可能になり、並行処理において非常に有用です。ファイルやメモリ上のデータなど、ランダムアクセスが可能なデータソースに対して実装されます。
bytes.Reader
とstrings.Reader
Goの標準ライブラリには、バイトスライスや文字列をio.Reader
インターフェースとして扱うための具体的な実装が提供されています。
bytes.Reader
:[]byte
(バイトスライス)を読み取り可能なストリームとして扱います。strings.Reader
:string
(文字列)を読み取り可能なストリームとして扱います。
これらのReader
型は、内部に読み取り位置や、場合によっては直前に読み込んだルーン(Unicodeコードポイント)に関する情報(prevRune
など)を保持しています。
データ競合 (Data Race)
データ競合は、複数のゴルーチンが同時に同じメモリ位置にアクセスし、少なくとも1つのアクセスが書き込みであり、かつそれらのアクセスが同期メカニズムによって順序付けされていない場合に発生するプログラミング上のバグです。データ競合が発生すると、プログラムの動作が予測不能になったり、クラッシュしたりする可能性があります。
ReadAt
メソッドは、その性質上、並行して呼び出されることが想定されるため、内部状態をミューテート(変更)するとデータ競合のリスクが高まります。
r.prevRune = -1
の意味
r.prevRune
は、bytes.Reader
やstrings.Reader
が内部的に保持するフィールドで、UnreadRune
メソッド(直前に読み込んだルーンをストリームに戻す)をサポートするために、直前に読み込んだルーンの情報を格納します。-1
は、有効なルーンが読み込まれていない状態を示すことが多いです。
ReadAt
メソッド内でr.prevRune = -1
と設定することは、ReadAt
が呼び出された際に、UnreadRune
の内部状態をリセットすることを意味します。しかし、前述の通り、ReadAt
はストリームの現在位置やその他の内部状態を変更すべきではないため、この操作はReadAt
のセマンティクスに反し、並行処理における問題を引き起こす可能性がありました。
技術的詳細
このコミットの技術的な核心は、io.ReaderAt
インターフェースのセマンティクスを厳密に遵守することにあります。io.ReaderAt
のドキュメントには、「ReadAt
は、基礎となる入力ストリームのオフセットを変更しない」と明記されています。この「オフセット」は、単に読み取り位置だけでなく、Reader
が持つ他の内部状態(例えばprevRune
)にも適用されるべきであるという解釈が、この修正の根底にあります。
CL 77580046
では、bytes.Reader
とstrings.Reader
のReadAt
メソッドに以下の行が追加されました。
r.prevRune = -1
この変更は、ReadAt
が呼び出された際に、Reader
のprevRune
フィールドを-1
にリセットすることを意味します。prevRune
は、UnreadRune
メソッドが正しく機能するために、直前に読み込まれたルーンの情報を保持する内部状態です。
しかし、ReadAt
はランダムアクセスを目的としたメソッドであり、ストリームの現在位置やUnreadRune
の状態のような内部状態を変更すべきではありません。もし複数のゴルーチンが同時にReadAt
を呼び出し、その中でr.prevRune
が変更されると、UnreadRune
を使用する他の操作(例えば、同じReader
インスタンスに対してRead
やUnreadRune
を呼び出すゴルーチン)との間でデータ競合が発生する可能性がありました。特に、ReadAt
がprevRune
をリセットすることで、UnreadRune
が期待する値を見つけられなくなり、テストが失敗する原因となりました。
このコミットでは、CL 77580046
で追加されたr.prevRune = -1
の行を削除することで、ReadAt
メソッドがReader
の内部状態を一切変更しないように修正しています。これにより、ReadAt
の呼び出しが副作用を持たなくなり、並行処理環境下での安全性が確保されます。
また、テストファイル(reader_test.go
とstrings_test.go
)からReadAt
に関連するテストケースが削除されているのは、おそらくUnreadRuneErrorTests
というテストスイートが、ReadAt
がprevRune
をリセットするという誤った前提に基づいて設計されていたためと考えられます。ReadAt
がprevRune
をリセットしないように修正されたため、その前提に基づくテストは不要になったか、あるいは不適切になったため削除されたと推測されます。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更は、以下の2つのファイルにおけるReadAt
メソッドからの1行の削除です。
-
src/pkg/bytes/reader.go
--- a/src/pkg/bytes/reader.go +++ b/src/pkg/bytes/reader.go @@ -43,7 +43,6 @@ func (r *Reader) Read(b []byte) (n int, err error) { } func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) { - r.prevRune = -1 if off < 0 { return 0, errors.New("bytes: invalid offset") }
-
src/pkg/strings/reader.go
--- a/src/pkg/strings/reader.go +++ b/src/pkg/strings/reader.go @@ -42,7 +42,6 @@ func (r *Reader) Read(b []byte) (n int, err error) { } func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) { - r.prevRune = -1 if off < 0 { return 0, errors.New("strings: invalid offset") }
また、関連するテストファイルからもReadAt
に関するテストケースが削除されています。
-
src/pkg/bytes/reader_test.go
--- a/src/pkg/bytes/reader_test.go +++ b/src/pkg/bytes/reader_test.go @@ -138,7 +138,6 @@ var UnreadRuneErrorTests = []struct { f func(*Reader) }{ {"Read", func(r *Reader) { r.Read([]byte{}) }}, - {"ReadAt", func(r *Reader) { r.ReadAt([]byte{}, 0) }}, {"ReadByte", func(r *Reader) { r.ReadByte() }}, {"UnreadRune", func(r *Reader) { r.UnreadRune() }}, {"Seek", func(r *Reader) { r.Seek(0, 1) }},
-
src/pkg/strings/strings_test.go
--- a/src/pkg/strings/strings_test.go +++ b/src/pkg/strings/strings_test.go @@ -863,7 +863,6 @@ var UnreadRuneErrorTests = []struct { f func(*Reader) }{ {"Read", func(r *Reader) { r.Read([]byte{}) }}, - {"ReadAt", func(r *Reader) { r.ReadAt([]byte{}, 0) }}, {"ReadByte", func(r *Reader) { r.ReadByte() }}, {"UnreadRune", func(r *Reader) { r.UnreadRune() }}, {"Seek", func(r *Reader) { r.Seek(0, 1) }},
コアとなるコードの解説
このコミットの核心は、ReadAt
メソッドが「レシーバをミューテートしない」というio.ReaderAt
インターフェースの重要な契約を再確立することです。
bytes.Reader
とstrings.Reader
のReadAt
メソッドからr.prevRune = -1
という行が削除されたことで、ReadAt
の呼び出しはReader
インスタンスのprevRune
フィールドに影響を与えなくなりました。これにより、以下の重要な点が保証されます。
- 副作用の排除:
ReadAt
は、データの読み取り以外の副作用(この場合は内部状態の変更)を持たなくなります。これは、関数型プログラミングの原則にも通じる、より予測可能で安全なコードの実現に貢献します。 - 並行処理の安全性向上: 複数のゴルーチンが同じ
Reader
インスタンスに対して同時にReadAt
を呼び出しても、prevRune
フィールドを巡るデータ競合が発生しなくなります。ReadAt
はオフセット指定によるランダムアクセスを意図しているため、並行アクセスされることが多く、この変更は並行処理の堅牢性を高めます。 io.ReaderAt
セマンティクスの遵守:io.ReaderAt
インターフェースのドキュメントに明記されている「基礎となる入力ストリームのオフセットを変更しない」という契約を、より広範な意味で遵守することになります。これは、単に読み取り位置だけでなく、UnreadRune
のような他の操作に影響を与える可能性のある内部状態も変更しないことを意味します。
テストファイルからのReadAt
関連のテストケースの削除は、ReadAt
がprevRune
をリセットするという誤った前提に基づいていたテストが、この修正によって不要になったか、あるいは不適切になったためと考えられます。ReadAt
がprevRune
をリセットしないという正しい挙動になったため、その挙動を期待するテストはもはや意味をなさなくなった、と解釈できます。
この修正は、Go言語の標準ライブラリが提供するインターフェースのセマンティクスを厳密に守り、並行処理における潜在的なバグを未然に防ぐための重要なステップと言えます。
関連リンク
- Go言語の
io
パッケージドキュメント: https://pkg.go.dev/io - Go言語の
bytes
パッケージドキュメント: https://pkg.go.dev/bytes - Go言語の
strings
パッケージドキュメント: https://pkg.go.dev/strings - Go言語におけるデータ競合の検出 (Go Race Detector): https://go.dev/doc/articles/race_detector
参考にした情報源リンク
- Go言語の公式ドキュメント
- Go言語のソースコード
- Go言語の
io.ReaderAt
インターフェースに関する一般的な解説 - データ競合に関する一般的なプログラミングの知識
- Go言語のコードレビューシステム (Gerrit) のCL (Change List) の概念