[インデックス 1526] ファイルの概要
このコミットでは、Go言語の初期開発段階において存在した export キーワードが削除されました。この変更は、Go言語の設計思想である「シンプルさ」と「明示的な宣言の削減」を追求する一環として行われました。具体的には、Go言語の識別子の可視性(エクスポートされるか否か)を、その識別子の先頭文字が大文字か小文字かによって決定するという、現在のGo言語の慣習が確立される過渡期の重要な変更点となります。
変更されたファイルは多岐にわたり、Go言語の標準ライブラリ、コンパイラ関連のコード、およびテストファイルなど、合計234ファイルに影響が及んでいます。これは、export キーワードが言語の広範な部分で使用されていたことを示しています。
主な変更ファイルは以下の通りです。
doc/progs/fd.godoc/progs/sort.gosrc/cmd/gc/sys.gosrc/lib/bignum.gosrc/lib/bignum_test.gosrc/lib/bufio.gosrc/lib/bufio_test.gosrc/lib/container/array/array.gosrc/lib/container/array/array_test.gosrc/lib/container/array/intarray.gosrc/lib/flag.gosrc/lib/fmt/fmt_test.gosrc/lib/fmt/format.gosrc/lib/fmt/print.gosrc/lib/hash/adler32.gosrc/lib/hash/adler32_test.gosrc/lib/hash/crc32.gosrc/lib/hash/crc32_test.gosrc/lib/hash/md5.gosrc/lib/hash/md5_test.gosrc/lib/hash/sha1.gosrc/lib/hash/sha1_test.gosrc/lib/http/conn.gosrc/lib/http/request.gosrc/lib/http/server.gosrc/lib/http/url.gosrc/lib/io/bytebuffer.gosrc/lib/io/io.gosrc/lib/json/generic.gosrc/lib/json/generic_test.gosrc/lib/json/parse.gosrc/lib/json/struct.gosrc/lib/json/struct_test.gosrc/lib/malloc.gosrc/lib/math/all_test.gosrc/lib/math/asin.gosrc/lib/math/atan.gosrc/lib/math/atan2.gosrc/lib/math/const.gosrc/lib/math/exp.gosrc/lib/math/fabs.gosrc/lib/math/floor.gosrc/lib/math/fmod.gosrc/lib/math/hypot.gosrc/lib/math/log.gosrc/lib/math/pow.gosrc/lib/math/pow10.gosrc/lib/math/sin.gosrc/lib/math/sinh.gosrc/lib/math/sqrt.gosrc/lib/math/tan.gosrc/lib/math/tanh.gosrc/lib/net/dialgoogle_test.gosrc/lib/net/dnsclient.gosrc/lib/net/dnsconfig.gosrc/lib/net/dnsmsg.gosrc/lib/net/fd.gosrc/lib/net/fd_darwin.gosrc/lib/net/fd_linux.gosrc/lib/net/ip.gosrc/lib/net/ip_test.gosrc/lib/net/net.gosrc/lib/net/net_darwin.gosrc/lib/net/net_linux.gosrc/lib/net/parse_test.gosrc/lib/net/port.gosrc/lib/net/port_test.gosrc/lib/net/tcpserver_test.gosrc/lib/once.gosrc/lib/once_test.gosrc/lib/os/os_env.gosrc/lib/os/os_error.gosrc/lib/os/os_file.gosrc/lib/os/os_time.gosrc/lib/rand.gosrc/lib/reflect/all_test.gosrc/lib/reflect/tostring.gosrc/lib/reflect/type.gosrc/lib/reflect/value.gosrc/lib/regexp/all_test.gosrc/lib/regexp/regexp.gosrc/lib/sort.gosrc/lib/sort_test.gosrc/lib/strconv/atof.gosrc/lib/strconv/atof_test.gosrc/lib/strconv/atoi.gosrc/lib/strconv/atoi_test.gosrc/lib/strconv/decimal_test.gosrc/lib/strconv/fp_test.gosrc/lib/strconv/ftoa.gosrc/lib/strconv/ftoa_test.gosrc/lib/strconv/itoa.gosrc/lib/strconv/itoa_test.gosrc/lib/strconv/quote.gosrc/lib/strconv/quote_test.gosrc/lib/strings.gosrc/lib/strings_test.gosrc/lib/sync/mutex.gosrc/lib/sync/mutex_test.gosrc/lib/syscall/errstr_darwin.gosrc/lib/syscall/errstr_linux.gosrc/lib/syscall/file_darwin.gosrc/lib/syscall/file_linux.gosrc/lib/syscall/signal_amd64_darwin.gosrc/lib/syscall/signal_amd64_linux.gosrc/lib/syscall/socket_darwin.gosrc/lib/syscall/socket_linux.gosrc/lib/syscall/syscall.gosrc/lib/syscall/syscall_amd64_darwin.gosrc/lib/syscall/syscall_amd64_linux.gosrc/lib/syscall/time_amd64_darwin.gosrc/lib/syscall/time_amd64_linux.gosrc/lib/syscall/types_amd64_darwin.gosrc/lib/syscall/types_amd64_linux.gosrc/lib/tabwriter/tabwriter.gosrc/lib/tabwriter/tabwriter_test.gosrc/lib/testing.gosrc/lib/time/tick.gosrc/lib/time/tick_test.gosrc/lib/time/time.gosrc/lib/time/time_test.gosrc/lib/time/zoneinfo.gosrc/lib/unicode/letter.gosrc/lib/unicode/letter_test.gosrc/lib/utf8.gosrc/lib/utf8_test.gotest/235.gotest/bigalg.gotest/bugs/bug117.gotest/bugs/bug121.gotest/bugs/bug123.gotest/bugs/bug130.gotest/chan/fifo.gotest/chan/powser1.gotest/chan/powser2.gotest/chan/select.gotest/chan/sieve.gotest/complit.gotest/export.gotest/fixedbugs/bug007.gotest/fixedbugs/bug011.gotest/fixedbugs/bug023.gotest/fixedbugs/bug025.gotest/fixedbugs/bug026.gotest/fixedbugs/bug027.gotest/fixedbugs/bug028.gotest/fixedbugs/bug044.gotest/fixedbugs/bug045.gotest/fixedbugs/bug046.gotest/fixedbugs/bug054.gotest/fixedbugs/bug057.gotest/fixedbugs/bug058.gotest/fixedbugs/bug059.gotest/fixedbugs/bug066.gotest/fixedbugs/bug075.gotest/fixedbugs/bug083.dir/bug0.gotest/fixedbugs/bug084.gotest/fixedbugs/bug088.dir/bug0.gotest/fixedbugs/bug089.gotest/fixedbugs/bug093.gotest/fixedbugs/bug096.gotest/fixedbugs/bug097.gotest/fixedbugs/bug098.gotest/fixedbugs/bug099.gotest/fixedbugs/bug106.dir/bug0.gotest/fixedbugs/bug111.gotest/fixedbugs/bug112.gotest/fixedbugs/bug113.gotest/fixedbugs/bug114.gotest/fixedbugs/bug118.gotest/fixedbugs/bug120.gotest/func.gotest/hashmap.gotest/hilbert.gotest/interface.gotest/interface1.gotest/interface2.gotest/interface3.gotest/interface4.gotest/interface5.gotest/interface6.gotest/iota.gotest/ken/chan.gotest/ken/embed.gotest/ken/interbasic.gotest/ken/interfun.gotest/ken/intervar.gotest/ken/ptrfun.gotest/ken/rob1.gotest/ken/rob2.gotest/ken/robfunc.gotest/mallocrand.gotest/mallocrep1.gotest/map.gotest/method.gotest/method1.gotest/method2.gotest/method3.gotest/nil.gotest/peano.gotest/sieve.gotest/test0.gotest/vectors.gousr/gri/gosrc/ast.gousr/gri/gosrc/base.gousr/gri/gosrc/compilation.gousr/gri/gosrc/decls.gousr/gri/gosrc/export.gousr/gri/gosrc/expr.gousr/gri/gosrc/globals.gousr/gri/gosrc/import.gousr/gri/gosrc/object.gousr/gri/gosrc/parser.gousr/gri/gosrc/platform.gousr/gri/gosrc/printer.gousr/gri/gosrc/scanner.gousr/gri/gosrc/test/b.gousr/gri/gosrc/test/c.gousr/gri/gosrc/test/d.gousr/gri/gosrc/type.gousr/gri/gosrc/universe.gousr/gri/gosrc/utils.gousr/gri/gosrc/verifier.gousr/gri/pretty/ast.gousr/gri/pretty/compilation.gousr/gri/pretty/parser.gousr/gri/pretty/platform.gousr/gri/pretty/printer.gousr/gri/pretty/scanner.gousr/gri/pretty/selftest0.gousr/gri/pretty/selftest2.gousr/gri/pretty/typechecker.gousr/gri/pretty/universe.gousr/gri/pretty/utils.go
コミット
commit 839a68469b6f8bf40620a7977041e089bbd0eba3
Author: Russ Cox <rsc@golang.org>
Date: Tue Jan 20 14:40:40 2009 -0800
delete export
TBR=r
OCL=23121
CL=23127
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/839a68469b6f8bf40620a7977041e089bbd0eba3
元コミット内容
delete export
変更の背景
このコミットは、Go言語の初期設計における重要な変更点の一つです。Go言語は当初、他の多くのプログラミング言語と同様に、外部に公開する(エクスポートする)識別子に対して明示的な export キーワードを使用していました。しかし、Go言語の設計者たちは、言語のシンプルさとコードの読みやすさを追求する中で、この export キーワードの必要性について再検討しました。
export キーワードは、コードの冗長性を生み出し、特に大規模なコードベースではその管理が煩雑になる可能性がありました。また、Go言語の設計哲学には「明示的であることよりも、慣習によってコードの意図を伝えること」という考え方があります。この哲学に基づき、識別子の可視性を明示的なキーワードではなく、命名規則によって表現する方がよりGoらしいアプローチであると判断されました。
この変更により、Go言語は現在の「識別子の先頭文字が大文字であればエクスポートされ、小文字であればパッケージ内部に限定される」という、非常にシンプルかつ強力な可視性ルールを採用することになります。このコミットは、その移行期における export キーワードの完全な削除を意味し、Go言語の設計が現在の形に収斂していく上で不可欠なステップでした。
前提知識の解説
Go言語における「エクスポート」とは、パッケージの外部からアクセス可能にする、つまり公開することを指します。Go言語では、変数、関数、型、構造体のフィールドなど、あらゆる識別子に対してこの可視性ルールが適用されます。
現在のGo言語では、識別子の可視性は以下のシンプルなルールによって決定されます。
-
エクスポートされた識別子 (Exported Identifiers):
- 識別子の先頭文字が大文字である場合、その識別子はエクスポートされます。
- エクスポートされた識別子は、その識別子が定義されているパッケージの外部から参照・利用することができます。
- 例:
fmt.Println,math.Pi,http.Getなど。これらはすべて先頭が大文字であるため、Goの標準ライブラリの外部から利用可能です。
-
エクスポートされない識別子 (Unexported Identifiers):
- 識別子の先頭文字が小文字である場合、その識別子はエクスポートされません。
- エクスポートされない識別子は、その識別子が定義されているパッケージの内部からのみ参照・利用することができます。パッケージの外部からはアクセスできません。
- 例:
internal/ディレクトリ内のパッケージや、パッケージ内部のヘルパー関数、プライベートな構造体フィールドなど。
このルールは、Go言語のAPI設計において非常に重要です。開発者は、パッケージの公開インターフェースを明確に定義するために、どの識別子を大文字で始め、どの識別子を小文字で始めるかを意識してコードを書きます。これにより、不必要な内部実装の詳細が外部に漏れることを防ぎ、パッケージの凝集度を高め、疎結合なシステムを構築するのに役立ちます。
このコミット以前は、この大文字・小文字のルールに加えて export キーワードが必要でしたが、このコミットによって export キーワードが廃止され、現在のシンプルな命名規則のみで可視性が制御されるようになりました。
技術的詳細
export キーワードの削除は、Go言語のコンパイラとツールチェーンに大きな影響を与えました。
-
コンパイラの変更:
- コンパイラは、識別子の可視性を判断する際に、
exportキーワードの有無をチェックするロジックを削除し、代わりに識別子の先頭文字のケース(大文字か小文字か)をチェックするように変更されました。 - これにより、パーサーは
exportキーワードを特別なトークンとして認識する必要がなくなり、言語の文法が簡素化されました。 - コンパイル時の処理がわずかに効率化された可能性があります。キーワードの解析と管理のオーバーヘッドがなくなるためです。
- コンパイラは、識別子の可視性を判断する際に、
-
言語仕様の簡素化:
exportキーワードの削除は、Go言語の仕様自体を簡素化しました。開発者は、可視性を制御するために追加のキーワードを覚える必要がなくなり、命名規則という自然な方法でその意図を表現できるようになりました。- これは、Go言語の設計哲学である「シンプルさ」と「明示的な宣言の削減」に合致しています。
-
コードベース全体への影響:
- このコミットが示すように、
exportキーワードはGo言語の初期のコードベース全体で広く使用されていました。そのため、この変更は非常に大規模なリファクタリングを伴いました。 - すべての
exportキーワードを削除し、必要に応じて識別子の先頭文字を大文字に変更する作業が行われました。これにより、既存のコードが新しい可視性ルールに準拠するようになりました。 - テストファイルも同様に更新され、新しい可視性ルールが正しく機能することを確認しました。
- このコミットが示すように、
-
可読性と保守性の向上:
- 命名規則による可視性制御は、コードの可読性を向上させます。開発者は、識別子を見ただけでそれがパッケージの外部からアクセス可能かどうかを直感的に判断できます。
- また、新しい識別子を定義する際に、可視性を意識した命名を自然に行うようになり、コードベース全体の整合性が保たれやすくなります。
- これにより、長期的なコードの保守性も向上します。
この変更は、Go言語がその初期段階で、より洗練された、そして「Goらしい」設計へと進化していく過程における重要なマイルストーンと言えます。
コアとなるコードの変更箇所
このコミットのコアとなる変更は、Go言語のソースコード全体から export キーワードを削除することです。以下に、その典型的な変更例をいくつか示します。
例1: 構造体の定義
doc/progs/fd.go ファイルの変更:
--- a/doc/progs/fd.go
+++ b/doc/progs/fd.go
@@ -9,7 +9,7 @@ import (
"syscall";
)
-export type FD struct {
+type FD struct {
fildes int64; // file descriptor number
name string; // file name at Open time
}
例2: 変数の宣言
doc/progs/fd.go ファイルの変更:
--- a/doc/progs/fd.go
+++ b/doc/progs/fd.go
@@ -21,13 +21,13 @@ func newFD(fd int64, name string) *FD {
return &FD{fd, name}
}
-export var (
+var (
Stdin = newFD(0, "/dev/stdin");
Stdout = newFD(1, "/dev/stdout");
Stderr = newFD(2, "/dev/stderr");
)
例3: 関数の定義
doc/progs/sort.go ファイルの変更:
--- a/doc/progs/sort.go
+++ b/doc/progs/sort.go
@@ -4,13 +4,13 @@
package sort
-export type SortInterface interface {
+type SortInterface interface {
Len() int;
Less(i, j int) bool;
Swap(i, j int);
}
-export func Sort(data SortInterface) {
+func Sort(data SortInterface) {
for i := 1; i < data.Len(); i++ {
for j := i; j > 0 && data.Less(j, j-1); j-- {
data.Swap(j, j-1);
これらの例は、type、var、func の宣言の前にあった export キーワードが単純に削除されていることを示しています。識別子自体(FD, Stdin, SortInterface, Sort など)は、すでに先頭が大文字であるため、この変更後もエクスポートされたままとなります。
コアとなるコードの解説
上記のコード変更は、Go言語の可視性ルールが export キーワードから命名規則へと完全に移行したことを明確に示しています。
-
export type FD struct { ... }からtype FD struct { ... }へ:- 変更前は、
FD型がパッケージ外部に公開されることを明示的にexportキーワードで示していました。 - 変更後は、
exportキーワードが削除されていますが、型名FDの先頭文字がF(大文字) であるため、Go言語の新しい可視性ルールに従って引き続きエクスポートされます。これにより、冗長なキーワードが不要になり、コードがより簡潔になります。
- 変更前は、
-
export var (...)からvar (...)へ:Stdin,Stdout,Stderrといった標準入出力に関連する変数も同様に、exportキーワードが削除されています。- これらの変数名も先頭が大文字であるため、パッケージ外部からアクセス可能です。
-
export func Sort(...)からfunc Sort(...)へ:Sort関数やSortInterfaceインターフェースも、exportキーワードが削除されています。- 関数名やインターフェース名の先頭が大文字であるため、これらは引き続きエクスポートされ、他のパッケージから利用できます。
この変更の意図は、Go言語の設計哲学である「シンプルさ」と「明示的な宣言の削減」を徹底することにあります。export キーワードは、C++の public や Javaの public といったアクセス修飾子に似た役割を果たしていましたが、Go言語では、命名規則というより自然で直感的な方法で同じ目的を達成できると判断されました。
これにより、Goのコードはより読みやすく、記述しやすくなり、開発者は可視性を制御するために追加の構文を覚える必要がなくなりました。この変更は、Go言語が現在の成功を収める上で基盤となった、そのミニマリストな設計アプローチを象徴するものです。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/doc/
- Go言語のパッケージの可視性に関する公式ブログ記事やチュートリアル (このコミット後の情報):
- Effective Go - Names: https://go.dev/doc/effective_go#names
- A Tour of Go - Exported names: https://go.dev/tour/basics/3
参考にした情報源リンク
- Go言語におけるエクスポートの仕組みに関する記事:
- https://labex.io/ (Google Search結果より)
- https://www.digitalocean.com/community/tutorials/understanding-packages-in-go
- https://gitbooks.io/ (Google Search結果より)
- https://www.scaler.com/topics/go/exported-and-unexported-identifiers-in-go/
- https://go.dev/ (Google Search結果より)
- https://kodekloud.com/ (Google Search結果より)
- https://medium.com/ (Google Search結果より)
- Go 2における
exportキーワードの提案に関する議論 (採用されなかった提案):- https://github.com/golang/go/issues/20430 (Google Search結果より)