Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 1722] ファイルの概要

このコミットは、Go言語の標準ライブラリ src/lib/io/io.go における変数名の変更に関するものです。具体的には、fd という名前の変数を r にリネームしています。これは、コードの可読性とGo言語の慣習に合わせた命名規則への準拠を目的とした、典型的なリファクタリング作業です。

コミット

commit e9b40580ba724d3e2bc5552b3ee3277db9c26d58
Author: Russ Cox <rsc@golang.org>
Date:   Mon Mar 2 16:12:04 2009 -0800

    fix names: s/fd/r/
    
    R=r
    DELTA=9  (0 added, 0 deleted, 9 changed)
    OCL=25593
    CL=25593

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/e9b40580ba724d3e2bc5552b3ee3277db9c26d58

元コミット内容

fix names: s/fd/r/

このコミットメッセージは非常に簡潔で、「名前を修正する: fdr に置換する」という意味です。これは、コードベース全体で特定の変数名を一貫性のある、より適切な名前に変更するリファクタリング作業であることを示しています。

変更の背景

この変更の背景には、Go言語における慣用的な命名規則への準拠とコードの可読性向上が挙げられます。Go言語では、インターフェースのメソッド引数や構造体のフィールド名において、その型が持つ役割を簡潔に表現する一文字の変数名がよく用いられます。

元のコードでは fd という変数が使われていましたが、これは "file descriptor"(ファイル記述子)を想起させる可能性があります。しかし、Read インターフェースはファイルだけでなく、ネットワーク接続、メモリバッファなど、様々なデータソースからの読み込みを抽象化するものです。そのため、fd という名前は、その汎用性を適切に表現していませんでした。

r という名前は、Read インターフェースを実装するオブジェクト、すなわち「読み込み元 (reader)」を意味するGo言語の慣習的な命名です。この変更により、コードを読んだ際に、その変数が「読み込み可能な何か」であることを直感的に理解できるようになり、コードの意図がより明確になります。これは、Go言語の設計哲学である「シンプルさ」と「明瞭さ」に合致する変更と言えます。

前提知識の解説

Go言語のインターフェース

Go言語のインターフェースは、メソッドのシグネチャの集合を定義する型です。特定のインターフェースを実装する型は、そのインターフェースが定義するすべてのメソッドを持っている必要があります。Goのインターフェースは「暗黙的」であり、型がインターフェースのすべてのメソッドを実装していれば、明示的にそのインターフェースを実装すると宣言する必要はありません。

このコミットで関連するのは io.Reader インターフェースです。io.Reader は、Read(p []byte) (n int, err error) メソッドを持つインターフェースであり、バイト列を読み込むための汎用的な抽象化を提供します。

Go言語の命名規則

Go言語には、公式なスタイルガイドや慣習として推奨される命名規則がいくつかあります。

  • パッケージ名: 短く、すべて小文字で、単数形。
  • 変数名: 短く、意味が明確なもの。特に、ループ変数やインターフェースの引数など、スコープが狭い場合は一文字の変数名が頻繁に用いられます。
    • rio.Reader のインスタンスによく使われます。
    • wio.Writer のインスタンスによく使われます。
    • ctxcontext.Context のインスタンスによく使われます。
  • 関数名/メソッド名: CamelCase。エクスポートされる(外部から参照可能な)ものは大文字で始まる。
  • 構造体名: CamelCase。エクスポートされるものは大文字で始まる。

このコミットは、特に変数名の慣習、中でもインターフェースの引数に対する命名規則に焦点を当てています。

リファクタリング

リファクタリングとは、ソフトウェアの外部から見た動作を変えずに、内部構造を改善するプロセスです。目的は、コードの可読性、保守性、拡張性を高めることです。変数名の変更は、最も基本的なリファクタリング手法の一つであり、コードの意図をより明確にするために行われます。

技術的詳細

このコミットで行われた変更は、Go言語の io パッケージ内の Readn 関数と fullRead 構造体、および関連するメソッドにおける引数名とフィールド名の変更です。

Readn 関数の変更

元のシグネチャ: func Readn(fd Read, buf []byte) (n int, err *os.Error) 変更後: func Readn(r Read, buf []byte) (n int, err *os.Error)

Readn 関数は、指定されたバッファが満たされるまで、またはEOF(ファイルの終端)に達するかエラーが発生するまでデータを読み込む関数です。この関数は Read インターフェース(おそらく io.Reader のエイリアスか、当時のGoの io.Reader に相当するもの)を引数として受け取ります。

変更前は fd という名前が使われていましたが、これは "file descriptor" の略語として解釈されることが多く、ファイルシステムに特化した読み込み元を暗示します。しかし、Read インターフェースはファイルだけでなく、あらゆる種類のデータストリームからの読み込みを抽象化するものです。したがって、fd という名前は、この関数の汎用性を適切に表現していませんでした。

r という名前に変更することで、この引数が「読み込み可能なもの(reader)」全般を指すことが明確になります。これはGo言語の標準ライブラリ全体で広く採用されている慣習であり、コードの一貫性と可読性を向上させます。

fullRead 構造体とメソッドの変更

元の定義:

type fullRead struct {
	fd	Read;
}

func (fd *fullRead) Read(p []byte) (n int, err *os.Error) {
	n, err = Readn(fd.fd, p);
	return n, err
}

func MakeFullReader(fd Read) Read {
	if fr, ok := fd.(*fullRead); ok {
		// already a fullRead
		return fd
	}
	return &fullRead(fd)
}

変更後:

type fullRead struct {
	r	Read;
}

func (fr *fullRead) Read(p []byte) (n int, err *os.Error) {
	n, err = Readn(fr.r, p);
	return n, err
}

func MakeFullReader(r Read) Read {
	if fr, ok := r.(*fullRead); ok {
		// already a fullRead
		return r
	}
	return &fullRead(r)
}

fullRead 構造体は、Read インターフェースを実装するオブジェクトをラップし、その Read メソッドが常に Readn を呼び出すようにするアダプターのような役割を果たします。

  • 構造体フィールド名の変更: fd Read; から r Read; へ。これにより、構造体のフィールドが「読み込み元」であることを明確に示します。
  • レシーバ名の変更: func (fd *fullRead) から func (fr *fullRead) へ。Go言語では、メソッドのレシーバ名も短く、その型を簡潔に表す一文字または二文字の略語が慣習的に使われます。frfullRead の略であり、この慣習に沿っています。
  • MakeFullReader 関数の引数名の変更: func MakeFullReader(fd Read) から func MakeFullReader(r Read) へ。この関数は Read インターフェースを実装するオブジェクトを受け取り、それを fullRead 型に変換またはラップします。ここでも fd から r への変更は、引数が汎用的な「読み込み元」であることを強調します。

これらの変更はすべて、コードのセマンティクス(意味)を変えることなく、その表現をGo言語の慣習により合致させるためのものです。これにより、Go言語のコードベース全体の一貫性が保たれ、新しい開発者がコードを理解しやすくなります。

コアとなるコードの変更箇所

src/lib/io/io.go ファイルにおいて、以下の変更が行われました。

  1. Readn 関数の引数名 fdr に変更。
    -func Readn(fd Read, buf []byte) (n int, err *os.Error) {
    +func Readn(r Read, buf []byte) (n int, err *os.Error) {
    
  2. Readn 関数内部での fd の使用箇所を r に変更。
    -		nn, e := fd.Read(buf[n:len(buf)]);
    +		nn, e := r.Read(buf[n:len(buf)]);
    
  3. fullRead 構造体のフィールド名 fdr に変更。
    -	fd	Read;
    +	r	Read;
    
  4. fullRead 構造体の Read メソッドのレシーバ名 fdfr に変更。
    -func (fd *fullRead) Read(p []byte) (n int, err *os.Error) {
    +func (fr *fullRead) Read(p []byte) (n int, err *os.Error) {
    
  5. fullRead 構造体の Read メソッド内部での fd.fd の使用箇所を fr.r に変更。
    -	n, err = Readn(fd.fd, p);
    +	n, err = Readn(fr.r, p);
    
  6. MakeFullReader 関数の引数名 fdr に変更。
    -func MakeFullReader(fd Read) Read {
    +func MakeFullReader(r Read) Read {
    
  7. MakeFullReader 関数内部での fd の使用箇所を r に変更。
    -	if fr, ok := fd.(*fullRead); ok {
    +	if fr, ok := r.(*fullRead); ok {
    
  8. MakeFullReader 関数内部での fd の返却箇所を r に変更。
    -		return fd
    +		return r
    
  9. MakeFullReader 関数内部での fullRead のインスタンス生成箇所を &fullRead(r) に変更。
    -	return &fullRead(fd)
    +	return &fullRead(r)
    

コアとなるコードの解説

このコミットは、Go言語の io パッケージにおける命名規則の統一と可読性向上を目的としたものです。

Readn 関数は、io.Reader インターフェース(当時の Read インターフェース)を実装する任意のデータソースから、指定されたバイト数だけデータを読み込むことを保証するユーティリティ関数です。元のコードでは、このデータソースを表す引数に fd という名前が付けられていました。これは "file descriptor" の略であり、ファイルに特化した読み込み元を暗示します。しかし、io.Reader はファイルだけでなく、ネットワークソケット、メモリバッファ、標準入力など、様々な種類のデータストリームを抽象化するために設計されています。したがって、fd という名前は、その汎用性を適切に表現していませんでした。

新しい引数名 r は、io.Reader インターフェースを実装するオブジェクトに対してGo言語で慣習的に用いられる名前です。これは「読み込み元(reader)」を簡潔に表し、その変数がファイルに限定されない、より一般的なデータソースであることを明確に示します。

同様に、fullRead 構造体は、Read インターフェースをラップし、その Read メソッドが常に Readn を呼び出すようにするアダプターパターンを実装しています。この構造体の内部フィールド名も fd から r に変更され、レシーバ名も fd から frfullRead の略)に変更されました。MakeFullReader 関数も同様に引数名を fd から r に変更しています。

これらの変更は、コードの機能的な振る舞いを一切変えることなく、Go言語の慣習に沿った命名を採用することで、コードベース全体の一貫性を高め、将来の保守や理解を容易にすることを目的としています。これは、Go言語の初期段階において、コードベースの品質と一貫性を確立するための重要なステップの一つと言えます。

関連リンク

参考にした情報源リンク

  • Go言語のコミット履歴 (GitHub): https://github.com/golang/go/commits/master
  • Go言語の初期の設計に関する議論(Goのメーリングリストやデザインドキュメントなど、当時の情報源を特定できればより良い)
  • Go言語の命名規則に関する一般的な記事やブログポスト(例: "Go Naming Conventions" で検索)
  • Go言語の io.Reader インターフェースに関する解説記事