[インデックス 1494] ファイルの概要
このコミットは、Go言語の公式ドキュメントに含まれるチュートリアル用サンプルコードにおいて、識別子の命名規則を修正したものです。具体的には、外部に公開する必要のない識別子(型、関数、変数など)の先頭文字を大文字から小文字に変更し、Go言語の可視性ルールに準拠させています。これにより、サンプルコードがよりGo言語の慣習に沿ったものとなり、読者にとって適切なコーディングスタイルを示す役割を果たします。
コミット
commit 293c8f8c6566ee5c0a667a4b4ccee2541b21e3a8
Author: Rob Pike <r@golang.org>
Date: Thu Jan 15 17:54:07 2009 -0800
casify tutorial examples
will bring document in line in a later CL, which may include revisiting some of the names
R=rsc
DELTA=58 (0 added, 0 deleted, 58 changed)
OCL=22906
CL=22908
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/293c8f8c6566ee5c0a667a4b4ccee2541b21e3a8
元コミット内容
casify tutorial examples
will bring document in line in a later CL, which may include revisiting some of the names
R=rsc
DELTA=58 (0 added, 0 deleted, 58 changed)
OCL=22906
CL=22908
変更の背景
このコミットの背景には、Go言語の設計思想と、その初期段階におけるドキュメントの整備があります。Go言語では、識別子の可視性(エクスポートされるか否か)がその先頭文字の大小によって決定されるという、非常にシンプルかつ強力なルールが採用されています。大文字で始まる識別子はパッケージ外からアクセス可能(エクスポートされる)であり、小文字で始まる識別子はパッケージ内でのみアクセス可能(エクスポートされない、プライベート)です。
コミットメッセージにある「casify tutorial examples」は、このGo言語の命名規則、特に可視性に関する慣習をチュートリアルコードに適用することを意味しています。初期のGo言語のドキュメントやサンプルコードでは、まだこの慣習が完全に統一されていなかった可能性があります。このコミットは、チュートリアルコードがGo言語のベストプラクティスと一致するように修正し、学習者が正しいコーディングスタイルを身につけられるようにすることを目的としています。
また、「will bring document in line in a later CL, which may include revisiting some of the names」という記述から、この変更がドキュメント全体の整合性を高める一連の作業の一部であり、将来的にはさらに命名規則の見直しが行われる可能性が示唆されています。これは、Go言語が進化する中で、その設計原則がコードベース全体にわたって徹底されていく過程を示しています。
前提知識の解説
Go言語のパッケージと可視性
Go言語のコードは「パッケージ」という単位で構成されます。パッケージは関連する機能や型をまとめる論理的なグループであり、ファイルシステム上のディレクトリに対応します。Go言語における可視性(Visibility)は、このパッケージの概念と密接に結びついています。
- エクスポートされた識別子 (Exported Identifiers): 識別子(変数、定数、関数、型、構造体のフィールド、インターフェースのメソッドなど)の先頭文字が大文字である場合、その識別子はエクスポートされます。エクスポートされた識別子は、そのパッケージをインポートする他のパッケージからアクセス可能です。これは、他の言語における
publicに相当します。 - エクスポートされない識別子 (Unexported Identifiers): 識別子の先頭文字が小文字である場合、その識別子はエクスポートされません。エクスポートされない識別子は、その識別子が定義されているパッケージ内からのみアクセス可能です。これは、他の言語における
privateやinternalに相当します。
このシンプルなルールにより、Go言語では明示的な public や private キーワードを使用することなく、コードの公開範囲を制御できます。これはGo言語の設計哲学である「シンプルさ」と「明示性」を反映しています。
チュートリアルコードの役割
プログラミング言語のチュートリアルコードは、単に機能の使い方を示すだけでなく、その言語のイディオム(慣用的な書き方)やベストプラクティスを伝える重要な役割を担っています。特にGo言語のように、特定の命名規則が言語のセマンティクスに影響を与える場合、チュートリアルコードがこれらの規則に厳密に従うことは、学習者が正しい習慣を身につける上で不可欠です。
このコミットは、Go言語の可視性ルールという基本的ながらも重要な概念を、チュートリアルコードを通じて正しく伝えるための修正であると言えます。
技術的詳細
このコミットの技術的詳細は、Go言語の識別子の命名規則、特に可視性に関するルールを、チュートリアルコードに適用した点に集約されます。
変更されたファイルは doc/progs/ ディレクトリ配下にあり、これらはGo言語の初期のチュートリアルやサンプルプログラムとして提供されていたものです。これらのファイルにおいて、以下のような変更が行われています。
-
型名の変更:
Readerインターフェースがreaderに。Rot13構造体がrotate13に。Request構造体がrequestに。BinOp型がbinOpに。T型がtestTypeに。Day構造体がdayに。DayArray型がdayArrayに。 これらの型は、それぞれのファイル内で完結しており、外部パッケージから直接参照される必要がないため、小文字始まりに変更されています。
-
関数名の変更:
NewRot13関数がnewRotate13に。NewFD関数がnewFDに。Run関数がrunに。Server関数がserverに。StartServer関数がstartServerに。Generate関数がgenerateに。Filter関数がfilterに。Sieve関数がsieveに。 これらの関数も、パッケージ内部でのみ使用されることを意図しているため、小文字始まりに変更されています。Go言語では、コンストラクタ関数(New...のような名前を持つ関数)も、その関数が返す型がエクスポートされない場合は、関数名自体も小文字始まりにするのが慣習です。
-
変数名の変更:
Space定数がkSpaceに、Newline定数がkNewlineに。Stdin,Stdout,Stderr変数の初期化部分でNewFDがnewFDに変更。SpaceとNewlineの変更は、単に小文字にするだけでなく、kプレフィックスが付与されています。これは、Go言語の初期の慣習で、定数であることを示すためにkを付けることがあった名残かもしれません。しかし、Go言語の公式スタイルガイドでは、定数に特別なプレフィックスを付けることは推奨されていません。このコミットのボディにある「will bring document in line in a later CL, which may include revisiting some of the names」という記述は、このような初期の慣習が後に見直される可能性を示唆していると考えられます。
これらの変更は、Go言語の可視性ルールを厳密に適用し、チュートリアルコードがGo言語のイディオムに沿ったものとなるようにするためのものです。これにより、学習者はGo言語のコードを読む際に、識別子の命名からその公開範囲を直感的に理解できるようになります。
コアとなるコードの変更箇所
このコミットでは、複数のGo言語のサンプルファイル (doc/progs/ ディレクトリ以下) にわたって、識別子の命名規則が変更されています。具体的な変更は、主に型名、関数名、および一部の変数名の先頭文字を大文字から小文字に変更するものです。
以下に、各ファイルにおける主要な変更箇所を抜粋して示します。
doc/progs/cat_rot13.go
type Reader interface->type reader interfacetype Rot13 struct->type rotate13 structfunc NewRot13(source Reader) *Rot13->func newRotate13(source reader) *rotate13func (r13 *Rot13) Read(...)->func (r13 *rotate13) Read(...)func (r13 *Rot13) String()->func (r13 *rotate13) String()// end of Rot13 implementation->// end of Rotate13 implementationfunc cat(r Reader)->func cat(r reader)r = NewRot13(r)->r = newRotate13(r)
doc/progs/echo.go
const ( Space = " "; Newline = "\n"; )->const ( kSpace = " "; kNewline = "\n"; )s += Space->s += kSpaces += Newline->s += kNewline
doc/progs/fd.go
func NewFD(fd int64, name string) *FD->func newFD(fd int64, name string) *FDStdin = NewFD(...),Stdout = NewFD(...),Stderr = NewFD(...)->Stdin = newFD(...),Stdout = newFD(...),Stderr = newFD(...)return NewFD(r, name), os.ErrnoToError(e)->return newFD(r, name), os.ErrnoToError(e)
doc/progs/print_string.go
type T struct { ... }->type testType struct { ... }func (t *T) String() string->func (t *testType) String() stringt := &T{...}->t := &testType{...}
doc/progs/server1.go
type Request struct { ... }->type request struct { ... }type BinOp (a, b int) int;->type binOp (a, b int) int;func Run(op *BinOp, request *Request)->func run(op *binOp, request *request)func Server(op *BinOp, service chan *Request, quit chan bool)->func server(op *binOp, service chan *request, quit chan bool)case request := <-service:->case req := <-service:go Run(op, request);->go run(op, req);func StartServer(op *BinOp) (service chan *Request, quit chan bool)->func startServer(op *binOp) (service chan *request, quit chan bool)service = make(chan *Request);->service = make(chan *request);go Server(op, service, quit);->go server(op, service, quit);adder, quit := StartServer(...)->adder, quit := startServer(...)var reqs [N]Request;->var reqs [N]request;
doc/progs/sieve.go
func Generate(ch chan int)->func generate(ch chan int)func Filter(in, out chan int, prime int)->func filter(in, out chan int, prime int)go Generate(ch);->go generate(ch);go Filter(ch, ch1, prime);->go filter(ch, ch1, prime);
doc/progs/sieve1.go
func Generate() chan int->func generate() chan intfunc Filter(in chan int, prime int) chan int->func filter(in chan int, prime int) chan intfunc Sieve() chan int->func sieve() chan intch := Generate();->ch := generate();ch = Filter(ch, prime);->ch = filter(ch, prime);primes := Sieve();->primes := sieve();
doc/progs/sortmain.go
type Day struct { ... }->type day struct { ... }type DayArray struct { ... }->type dayArray struct { ... }func (p *DayArray) Len() int->func (p *dayArray) Len() intfunc (p *DayArray) Less(i, j int) bool->func (p *dayArray) Less(i, j int) boolfunc (p *DayArray) Swap(i, j int)->func (p *dayArray) Swap(i, j int)Sunday := Day{...},Monday := Day{...}, ... ->Sunday := day{...},Monday := day{...}, ...data := []*Day{...}->data := []*day{...}a := DayArray{data};->a := dayArray{data};
コアとなるコードの解説
これらの変更は、Go言語の可視性ルール(エクスポートルール)をチュートリアルコードに適用したものです。Go言語では、識別子(変数、関数、型など)の先頭文字が大文字であればその識別子はパッケージ外に公開され(エクスポート)、小文字であればパッケージ内に限定されます(エクスポートされない)。
変更されたコードはすべて doc/progs/ ディレクトリにあり、これらはGo言語のチュートリアルやサンプルとして提供されているプログラムです。これらのプログラムは、通常、単一のパッケージ内で完結しており、その内部の型や関数が外部のパッケージから直接参照されることは想定されていません。
したがって、このコミットで行われた変更は、これらの内部的な識別子を小文字始まりにすることで、Go言語の可視性ルールに準拠させ、コードの意図をより明確にするものです。これにより、チュートリアルコードはGo言語のベストプラクティスを反映し、学習者がGo言語のイディオムを正しく理解する手助けとなります。
例えば、cat_rot13.go の Rot13 型や NewRot13 関数は、そのファイル(およびパッケージ)の内部でのみ使用されるため、それぞれ rotate13 と newRotate13 に変更されています。同様に、server1.go の Request 型や Run 関数も、パッケージ内部でのみ利用されるため、request や run に変更されています。
echo.go における Space と Newline が kSpace と kNewline に変更された点は、Go言語の初期の慣習で定数に k プレフィックスを付けることがあった名残と考えられます。現在のGo言語のスタイルガイドでは、このようなプレフィックスは推奨されていませんが、このコミットが行われた時期(2009年)のGo言語の進化段階を反映していると言えます。
全体として、このコミットはGo言語の基本的な設計原則である「シンプルさ」と「明示性」を、チュートリアルコードを通じて徹底するための重要なステップでした。
関連リンク
- Go言語のパッケージと可視性 (Go言語公式ドキュメント - Effective Go: Names)
- Go言語の命名規則 (Go言語公式ドキュメント - CodeReviewComments: Naming)
参考にした情報源リンク
- Go言語の公式ドキュメント
- Go言語のソースコードリポジトリ (GitHub)
- Go言語の初期の設計に関する議論やメーリングリストのアーカイブ (必要に応じて)