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

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

このコミットは、Go言語の初期の仕様ドキュメントである doc/go_spec.html に、パッケージに関する記述の重要な更新と、チャネルの方向性に関する説明の微調整を加えるものです。特に、Goプログラムの構造におけるパッケージの役割、ソースファイルの構成、パッケージ句、インポート宣言の文法とセマンティクスについて詳細化されています。

コミット

commit 4659685b8f5591cb539e3e52cc98672e9fc89e02
Author: Rob Pike <r@golang.org>
Date:   Mon Mar 2 16:17:29 2009 -0800

    Packages.
    
    DELTA=170  (73 added, 21 deleted, 76 changed)
    OCL=25556
    CL=25594
---\n doc/go_spec.html | 184 +++++++++++++++++++++++++++++++++++--------------------\n 1 file changed, 118 insertions(+), 66 deletions(-)

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

https://github.com/golang/go/commit/4659685b8f5591cb539e3e52cc98672e9fc89e02

元コミット内容

このコミットは、Go言語の仕様ドキュメント doc/go_spec.html における「Packages」セクションを大幅に改訂し、チャネルの方向性に関する説明を修正しています。主な変更点は以下の通りです。

  • チャネルの方向性に関する説明文の明確化。
  • パッケージの定義、ソースファイルの構成、パッケージ句、インポート宣言に関する記述の追加と修正。
  • 特に、インポート宣言における異なる形式(エイリアス付きインポート、パッケージ名省略インポート、ドットインポート)が、どのようにインポートされたパッケージの識別子にアクセスするかについての詳細な説明と例の追加。
  • 複数ファイルからなるパッケージの概念と、そのコンパイルに関する注意点の記述。
  • Go言語の並行素数篩(prime sieve)の例において、print 関数が fmt.Print に変更され、fmt パッケージのインポートが追加。

変更の背景

このコミットは、Go言語がまだ開発の初期段階にあった2009年に行われたものです。Go言語の設計目標の一つに、大規模なソフトウェア開発を容易にするための優れたパッケージ管理メカニズムの提供がありました。初期のGo言語では、パッケージの概念とインポートの仕組みが非常に重要であり、その仕様を明確に定義することは言語の安定性と普及のために不可欠でした。

この時期のGo言語のパッケージシステムは、GOPATH 環境変数と go get コマンドに深く関連しており、ソースコードベースの配布が特徴でした。バージョン管理やプロジェクト間の分離に関する課題は後にGo Modulesによって解決されますが、このコミットの時点では、パッケージの基本的な構造とインポートのセマンティクスを正確に記述することが最優先事項でした。

具体的には、以下の点が背景にあると考えられます。

  • 仕様の明確化: 言語の初期段階では、開発者や将来のユーザーがGoのパッケージシステムを正しく理解できるよう、公式ドキュメントでの詳細な説明が求められていました。
  • パッケージの重要性: Go言語では、コードの再利用性、モジュール性、名前空間の管理においてパッケージが中心的な役割を果たすため、その動作原理を正確に記述する必要がありました。
  • インポートの多様性: インポート宣言には複数の形式があり、それぞれが識別子のスコープとアクセス方法に異なる影響を与えるため、それらを網羅的に説明し、混乱を避けるための詳細な例が必要でした。
  • 並行処理の例の更新: Go言語の重要な特徴である並行処理を示す素数篩の例が、より標準的なI/O関数である fmt.Print を使用するように更新され、言語の進化に合わせてドキュメントも追従する必要がありました。

前提知識の解説

このコミットを理解するためには、Go言語における以下の基本的な概念を理解しておく必要があります。

1. パッケージ (Packages)

Go言語のプログラムは、パッケージと呼ばれる論理的な単位で構成されます。パッケージは、関連する型、定数、関数、変数の集合をカプセル化し、名前空間を提供します。これにより、コードのモジュール化、再利用、および名前の衝突の回避が可能になります。

  • パッケージ句 (Package Clause): 各Goソースファイルの先頭には package <パッケージ名> というパッケージ句が必要です。これにより、そのファイルがどのパッケージに属するかを宣言します。
  • エクスポートされた識別子 (Exported Identifiers): パッケージ内の識別子(変数、関数、型など)は、その名前が大文字で始まる場合、そのパッケージの外部からアクセス可能になります。これを「エクスポートされている」と言います。小文字で始まる識別子はパッケージ内部でのみ使用可能です。
  • 複数ファイルパッケージ: 同じパッケージに属する複数のソースファイルは、同じディレクトリに配置され、同じパッケージ名を宣言します。これらのファイルは、エクスポートされているかどうかにかかわらず、パッケージ内のすべての識別子にアクセスできます。

2. インポート宣言 (Import Declarations)

他のパッケージで定義された識別子を使用するには、そのパッケージをインポートする必要があります。インポート宣言は、import "path/to/package" の形式で記述されます。

インポート宣言にはいくつかの形式があり、それぞれがインポートされたパッケージの識別子へのアクセス方法に影響を与えます。

  • 通常インポート: import "fmt" のように記述します。この場合、fmt.Println のように、パッケージ名(fmt)をプレフィックスとして使用して識別子にアクセスします。
  • エイリアス付きインポート: import M "lib/math" のように、インポートするパッケージにローカルなエイリアス(M)を割り当てます。この場合、M.Sin のようにエイリアスを使用して識別子にアクセスします。
  • パッケージ名省略インポート: import "lib/math" のように、エイリアスを指定しない場合、インポートされたパッケージの宣言されたパッケージ名(例: math)がローカルな名前として使用されます。math.Sin のようにアクセスします。
  • ドットインポート (Dot Import): import . "lib/math" のように、パッケージ名の代わりにピリオド(.)を使用します。この場合、インポートされたパッケージのエクスポートされた識別子が、現在のパッケージのトップレベルスコープに直接追加されます。つまり、Sin のように、パッケージ名をプレフィックスなしで直接使用できます。ただし、名前の衝突が発生する可能性があるため、注意が必要です。

3. チャネル (Channels)

Go言語の並行処理の根幹をなす要素の一つがチャネルです。チャネルは、ゴルーチン間で値を送受信するための通信メカニズムを提供します。

  • チャネルの方向性: チャネルは、値を送受信できる双方向チャネル (chan T)、値のみを送信できる送信専用チャネル (chan <- T)、値のみを受信できる受信専用チャネル (<- chan T) の3つの方向性を持つことができます。このコミットでは、これらの説明文がより明確に修正されています。

技術的詳細

このコミットの技術的詳細は、主にGo言語の仕様ドキュメント doc/go_spec.html の「Packages」セクションの改訂に集約されます。

1. チャネル方向性の説明の明確化

コミットの冒頭部分では、チャネルの方向性に関する説明がより自然な表現に修正されています。

  • chan T // can send and receive values of type Tchan T // can be used to send and receive values of type T に変更。
  • <-chan int // can only receive ints<-chan int // can only be used to receive ints に変更。

これは、チャネルが「〜できる」という能力を示すのではなく、「〜のために使用できる」という用途を示す表現に統一されたものです。

2. パッケージセクションの構造化と詳細化

「Packages」セクションは、以前の簡潔な記述から、より詳細で構造化された説明へと進化しています。

  • 導入部分: Goプログラムがパッケージによって構築されること、パッケージがソースファイルから構成され、型、定数、関数、変数のインターフェースを提供すること、そしてそれらが他のパッケージでインポートされ使用されることが明確に述べられています。
  • Source file organization (ソースファイルの構成): 各ソースファイルがパッケージ句で始まり、その後にインポート宣言、そして関数、型、変数、定数の宣言が続くという構成が明記されています。また、パッケージ句に続くソーステキストがスコープのブロックとして機能することも言及されています。
    • 文法規則 Package = PackageClause { ImportDecl [ ";" ] } { Declaration [ ";" ] } .SourceFile = PackageClause { ImportDecl [ ";" ] } { Declaration [ ";" ] } . に変更され、より具体的な「SourceFile」という用語が導入されています。
  • Package clause (パッケージ句): パッケージ句が各ソースファイルの先頭にあり、そのファイルが属するパッケージを定義することが説明されています。
    • PackageClause = "package" PackageName . の文法規則が再掲され、package math の例が示されています。
    • 同じ PackageName を共有するファイルのセットがパッケージの実装を形成すること、そして実装によってはすべてのソースファイルが同じディレクトリに存在する必要があることが追記されています。
  • Import (インポート): インポート宣言に関する説明が大幅に拡張されています。
    • インポート宣言が、他のパッケージからエクスポートされた識別子にアクセスするための手段であることが述べられています。
    • インポート宣言が、インポートされたパッケージの内容にアクセスするために使用できる識別子と、パッケージの(コンパイル済み)実装を参照するファイル名を提供することが説明されています。ファイル名がインストールされたパッケージのリポジトリに対する相対パスである可能性も示唆されています。
    • 文法規則 ImportDecl, ImportSpecList, ImportSpec, PackageFileName が再掲されています。
    • インポート後の識別子アクセス: インポート後に、インポートされたパッケージ P からのエクスポートされた名前 N が、通常は修飾識別子 P.N でアクセスできることが詳細に説明されています。
      • 明示的なパッケージ名 p1 が提供された場合 (import p1 "lib/math")、p1.N の形式になること。
      • 名前が提供されない場合 (import "lib/math")、インポートされたパッケージのソースファイル内で宣言されたパッケージ名が P になること。
      • 明示的なピリオド(.)が使用された場合 (import . "lib/math")、N が現在のファイルのパッケージレベルスコープに現れ、修飾名が不要かつ誤りとなること。この形式では、名前の衝突が発生するとエラーになることが強調されています。
    • インポート形式の例: math パッケージが Sin 関数をエクスポートしていると仮定し、"lib/math" にコンパイル済みパッケージがインストールされている場合の、異なるインポート構文と Sin のローカルな名前の対応表が追加されています。
      Import syntax               Local name of Sin
      
      import M "lib/math"         M.Sin
      import   "lib/math"         math.Sin
      import . "lib/math"         Sin
      
      これは、Go言語のインポートのセマンティクスを非常に明確に示しています。
  • Multi-file packages (複数ファイルパッケージ): パッケージが複数のソースファイルから構成される場合の動作が説明されています。
    • パッケージレベルスコープのすべての名前(エクスポートされた名前だけでなく)が、パッケージ内のすべてのファイルから可視であること。
    • 名前を使用する意図を宣言するためにインポート宣言は依然として必要だが、インポートされた名前は修飾識別子なしでアクセスできること。
    • 複数ファイルパッケージのコンパイルには、パッケージ内でインポートされた名前の解決を満たす順序でファイルがコンパイルおよびインストールされる必要があること。
    • math1.gomath2.go の例が追加され、math1.go が先にコンパイルされてインストールされていれば、math2.go から SintwoPi に修飾識別子なしで直接参照できることが示されています。これは、Goのパッケージがコンパイル単位であり、同じパッケージ内のファイルは互いに可視であるという重要な概念を説明しています。

3. 素数篩の例の更新

Go言語の並行処理の例として示されている素数篩のコードが更新されています。

  • print(prime, "\n");fmt.Print(prime, "\n"); に変更されました。
  • これに伴い、import "fmt" が追加されました。

これは、Go言語の標準ライブラリである fmt パッケージの Print 関数を使用するように、より慣用的なGoコードに修正されたことを意味します。初期のGoには組み込みの print 関数がありましたが、後に fmt パッケージに移行されました。

4. コメントアウトされたTODOの削除

以前のコミットで追加された、if ステートメントの文法に関するTODOコメントが削除されています。これは、そのTODOが解決されたか、あるいは仕様の記述方法が変更されたことを示唆しています。

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

このコミットは doc/go_spec.html ファイルのみを変更しています。以下に主要な変更箇所を抜粋し、その意味を解説します。

--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1101,9 +1101,9 @@ to receive. This constraint is called a channel's <i>direction</i>; either
 </p>
 
 <pre>
-chan T         // can send and receive values of type T
+chan T         // can be used to send and receive values of type T
 chan <- float  // can only be used to send floats
-<-chan int     // can only receive ints
+<-chan int     // can only be used to receive ints
 </pre>
 
 <p>
@@ -3065,27 +3065,6 @@ if x := f(); x < y {
 </pre>
 
 
-<!--
-TODO: gri thinks that Statement needs to be changed as follows:
-
-	IfStat =
-	       "if" [ [ SimpleStat ] ";" ] [ Expression ] Block
-	       [ "else" ( IfStat | Block ) ] .
-
-To facilitate the "if else if" code pattern, if the "else" branch is
-simply another "if" statement, that "if" statement may be written
-without the surrounding Block:
-
-	if x > 0 {
-		return 0;
-	} else if x > 10 {
-		return 1;
-	} else {
-		return 2;
-	}
-
--->
-
 <h3>Switch statements</h3>
 
 <p>
@@ -3757,81 +3736,154 @@ m := make(map[string] int, 100);  # map with initial space for 100 elements
 
 <h2>Packages</h2>
 
-A package is a package clause, optionally followed by import declarations,
-followed by a series of declarations.
+<p>
+Go programs are constructed by linking together <i>packages</i>.
+A package is in turn constructed from one or more source files that
+together provide an interface to a set of types, constants, functions,
+and variables.  Those elements may be <i>imported</i> and used in
+another package.
+</p>
+\n+<h3>Source file organization</h3>
+\n+<p>
+Each source file consists of a package clause defining the package
+to which it belongs, followed by a possibly empty set of import
+declarations that declare packages whose contents it wishes to use,
+followed by a possibly empty set of declarations of functions,
+types, variables, and constants.  The source text following the
+package clause acts as a block for scoping ($Declarations and scope
+rules).
+</p>
 \n <pre class=\"grammar\">\n-Package = PackageClause { ImportDecl [ ";" ] } { Declaration [ ";" ] } .\n+SourceFile       = PackageClause { ImportDecl [ ";" ] } { Declaration [ ";" ] } .\n </pre>\n \n-The source text following the package clause acts like a block for scoping\n-purposes ($Declarations and scope rules).\n+<h3>Package clause</h3>
+\n <p>\n-Every source file identifies the package to which it belongs.\n-The file must begin with a package clause.\n+A package clause begins each source file and defines the package
+to which the file belongs.
+</p>
 \n <pre class=\"grammar\">\n-PackageClause = "package" PackageName .\n+PackageClause    = "package" PackageName .\n+</pre>
 \n-package Math
+<pre>
+package math
+</pre>
 \n+<p>
+A set of files sharing the same PackageName form the implementation of a package.
+An implementation may require that all source files for a package inhabit the same directory.
+</p>
 \n-A package can gain access to exported identifiers from another package\n-through an import declaration:\n+<h3>Import</h3>
+\n+<p>
+A source file gains access to exported identifiers (§Exported
+identifiers) from another package through an import declaration.
+In the general form, an import declaration provides an identifier
+that code in the source file may use to access the imported package's
+contents and a file name referring to the (compiled) implementation of
+the package.  The file name may be relative to a repository of
+installed packages.
+</p>
 \n <pre class=\"grammar\">\n-ImportDecl = "import" ( ImportSpec | "(" [ ImportSpecList ] ")" ) .\n-ImportSpecList = ImportSpec { ";" ImportSpec } [ ";" ] .\n-ImportSpec = [ "." | PackageName ] PackageFileName .\n-PackageFileName = StringLit .\n+ImportDecl       = "import" ( ImportSpec | "(" [ ImportSpecList ] ")" ) .\n+ImportSpecList   = ImportSpec { ";" ImportSpec } [ ";" ] .\n+ImportSpec       = [ "." | PackageName ] PackageFileName .\n+PackageFileName  = StringLit .\n </pre>\n \n-An import statement makes the exported package-level identifiers of the named\n-package file accessible to this package.\n <p>\n-In the following discussion, assume we have a package in the\n-file "/lib/math", called package "math", which exports the identifiers\n-"Sin" and "Cos" denoting the respective trigonometric functions.\n+After an import, in the usual case an exported name <i>N</i> from the imported\n+package <i>P</i> may be accessed by the qualified identifier\n+<i>P</i><code>.</code><i>N</i> (§Qualified identifiers).  The actual\n+name <i>P</i> depends on the form of the import declaration.  If\n+an explicit package name <code>p1</code> is provided, the qualified\n+identifer will have the form <code>p1.</code><i>N</i>.  If no name\n+is provided in the import declaration, <i>P</i> will be the package\n+name declared within the source files of the imported package.\n+Finally, if the import declaration uses an explicit period\n+(<code>.</code>) for the package name, <i>N</i> will appear\n+in the package-level scope of the current file and the qualified name is\n+unnecessary and erroneous.  In this form, it is an error if the import introduces\n+a name conflict.\n+</p>\n <p>\n-In the general form, with an explicit package name, the import\n-statement declares that package name as an identifier whose\n-contents are the exported elements of the imported package.\n-For instance, after\n+In this table, assume we have compiled a package named\n+<code>math</code>, which exports function <code>Sin</code>, and\n+installed the compiled package in file\n+<code>"lib/math"</code>.\n+</p>\n \n-<pre>\n-import M "/lib/math"\n+<pre class=\"grammar\">\n+Import syntax               Local name of Sin\n+\n+import M "lib/math"         M.Sin\n+import   "lib/math"         math.Sin\n+import . "lib/math"         Sin\n </pre>\n \n-the contents of the package /lib/math can be accessed by\n-"M.Sin", "M.Cos", etc.\n+<h3>Multi-file packages</h3>
+\n <p>\n-In its simplest form, with no package name, the import statement\n-implicitly uses the imported package name itself as the local\n-package name.  After\n+If a package is constructed from multiple source files, all names\n+at package-level scope, not just exported names, are visible to all the\n+files in the package. An import declaration is still necessary to\n+declare intention to use the names,\n+but the imported names do not need a qualified identifer to be\n+accessed.\n+</p>\n \n+<p>\n+The compilation of a multi-file package may require\n+that the files be compiled and installed in an order that satisfies\n+the resolution of names imported within the package.\n+</p>\n+\n+<p>\n+If source file <code>math1.go</code> contains\n+</p>\n <pre>\n-import "/lib/math"\n+package math\n+\n+const twoPi = 6.283185307179586\n+\n+function Sin(x float) float { return ... }\n </pre>\n \n-the contents are accessible by "math.Sin", "math.Cos".\n <p>\n-Finally, if instead of a package name the import statement uses\n-an explicit period, the contents of the imported package are added\n-to the current package. After\n-\n+and file <code>"math2.go"</code> begins\n+</p>\n <pre>\n-import . "/lib/math"\n+package math\n+\n+import "lib/math"\n </pre>\n \n-the contents are accessible by "Sin" and "Cos".  In this instance, it is\n-an error if the import introduces name conflicts.\n <p>\n-Here is a complete example Go package that implements a concurrent prime sieve:\n+then, provided <code>"math1.go"</code> is compiled first and\n+installed in <code>"lib/math"</code>, <code>math2.go</code>\n+may refer directly to <code>Sin</code> and <code>twoPi</code>\n+without a qualified identifier.\n+</p>\n+\n+<h3>An example package</h3>
+\n+<p>\n+Here is a complete Go package that implements a concurrent prime sieve.\n+</p>\n \n <pre>\n  package main\n \n+import "fmt"\n+\n  // Send the sequence 2, 3, 4, ... to channel 'ch'.\n  func generate(ch chan <- int) {\n  	for i := 2; ; i++ {\n@@ -3856,7 +3908,7 @@ func sieve() {\n  	go generate(ch);  // Start generate() as a subprocess.\n  	for {\n  		prime := <-ch;\n-\t\tprint(prime, "\\n");\n+\t\tfmt.Print(prime, "\\n");\n  		ch1 := make(chan int);\n  		go filter(ch, ch1, prime);\n  		ch = ch1\n@@ -3972,7 +4024,7 @@ Program execution begins by initializing the <code>main</code> package and then\n invoking <code>main.main()</code>.\n </p>\n <p>\n-When main.main() returns, the program exits.\n+When <code>main.main()</code> returns, the program exits.\n </p>\n \n <hr/>

コアとなるコードの解説

1. チャネル方向性の説明の修正

-chan T         // can send and receive values of type T
+chan T         // can be used to send and receive values of type T
-<-chan int     // can only receive ints
+<-chan int     // can only be used to receive ints

これは、チャネルの方向性に関する説明文をより正確で自然な英語表現に修正したものです。「〜できる」という直接的な表現から、「〜のために使用できる」という用途を示す表現に変更されています。これは、Go言語の仕様ドキュメントにおける表現の厳密性を高めるための細かな調整です。

2. if ステートメントに関するTODOコメントの削除

-<!--
-TODO: gri thinks that Statement needs to be changed as follows:
-...
--->

このセクション全体が削除されています。これは、以前に存在した if ステートメントの文法に関するTODO(将来的な変更の提案)が、このコミットの時点で不要になったか、あるいは別の方法で解決されたことを示しています。仕様が固まりつつある段階で、一時的なメモが整理されたものと考えられます。

3. 「Packages」セクションの大幅な改訂

このコミットの最も重要な変更点です。

導入部分の追加と文法規則の変更

-A package is a package clause, optionally followed by import declarations,
-followed by a series of declarations.
+<p>
+Go programs are constructed by linking together <i>packages</i>.
+A package is in turn constructed from one or more source files that
+together provide an interface to a set of types, constants, functions,
+and variables.  Those elements may be <i>imported</i> and used in
+another package.
+</p>
+\n+<h3>Source file organization</h3>
+\n+<p>
+Each source file consists of a package clause defining the package
+to which it belongs, followed by a possibly empty set of import
+declarations that declare packages whose contents it wishes to use,
+followed by a possibly empty set of declarations of functions,
+types, variables, and constants.  The source text following the
+package clause acts as a block for scoping ($Declarations and scope
+rules).
+</p>
 \n <pre class=\"grammar\">\n-Package = PackageClause { ImportDecl [ ";" ] } { Declaration [ ";" ] } .\n+SourceFile       = PackageClause { ImportDecl [ ";" ] } { Declaration [ ";" ] } .\n </pre>

以前の簡潔なパッケージの定義が、より詳細な導入文に置き換えられています。Goプログラムがパッケージによって構築され、パッケージがソースファイルから構成され、型、定数、関数、変数のインターフェースを提供し、それらがインポートされて使用されるという、パッケージの基本的な役割が明確に説明されています。

また、文法規則が Package から SourceFile に変更され、Goのソースファイルの構造をより正確に表現するようになりました。これは、Goのコンパイル単位が個々のソースファイルであることを示唆しています。

パッケージ句の説明の追加

-The source text following the package clause acts like a block for scoping
-purposes ($Declarations and scope rules).
+<h3>Package clause</h3>
+\n <p>
-Every source file identifies the package to which it belongs.\n-The file must begin with a package clause.\n+A package clause begins each source file and defines the package
+to which the file belongs.
+</p>
 \n <pre class=\"grammar\">\n-PackageClause = "package" PackageName .\n+PackageClause    = "package" PackageName .\n+</pre>
 \n-package Math
+<pre>
+package math
+</pre>
 \n+<p>
+A set of files sharing the same PackageName form the implementation of a package.
+An implementation may require that all source files for a package inhabit the same directory.
+</p>

パッケージ句に関する説明が独立したセクションとして追加され、その役割が明確化されました。特に、同じ PackageName を共有するファイルのセットがパッケージの実装を形成すること、そしてすべてのソースファイルが同じディレクトリに存在する必要がある場合があることが追記されています。これは、Goのパッケージがディレクトリ構造と密接に関連していることを示しています。

インポート宣言の詳細化と例の追加

-A package can gain access to exported identifiers from another package\n-through an import declaration:\n+<h3>Import</h3>
+\n+<p>
+A source file gains access to exported identifiers (§Exported
+identifiers) from another package through an import declaration.
+In the general form, an import declaration provides an identifier
+that code in the source file may use to access the imported package's
+contents and a file name referring to the (compiled) implementation of
+the package.  The file name may be relative to a repository of
+installed packages.
+</p>
 \n <pre class=\"grammar\">\n-ImportDecl = "import" ( ImportSpec | "(" [ ImportSpecList ] ")" ) .\n-ImportSpecList = ImportSpec { ";" ImportSpec } [ ";" ] .\n-ImportSpec = [ "." | PackageName ] PackageFileName .\n-PackageFileName = StringLit .\n+ImportDecl       = "import" ( ImportSpec | "(" [ ImportSpecList ] ")" ) .\n+ImportSpecList   = ImportSpec { ";" ImportSpec } [ ";" ] .\n+ImportSpec       = [ "." | PackageName ] PackageFileName .\n+PackageFileName  = StringLit .\n </pre>\n \n-<p>\n-In the following discussion, assume we have a package in the\n-file "/lib/math", called package "math", which exports the identifiers\n-"Sin" and "Cos" denoting the respective trigonometric functions.\n+<p>
+After an import, in the usual case an exported name <i>N</i> from the imported\n+package <i>P</i> may be accessed by the qualified identifier\n+<i>P</i><code>.</code><i>N</i> (§Qualified identifiers).  The actual\n+name <i>P</i> depends on the form of the import declaration.  If\n+an explicit package name <code>p1</code> is provided, the qualified\n+identifer will have the form <code>p1.</code><i>N</i>.  If no name\n+is provided in the import declaration, <i>P</i> will be the package\n+name declared within the source files of the imported package.\n+Finally, if the import declaration uses an explicit period\n+(<code>.</code>) for the package name, <i>N</i> will appear\n+in the package-level scope of the current file and the qualified name is\n+unnecessary and erroneous.  In this form, it is an error if the import introduces\n+a name conflict.\n+</p>\n <p>\n-In the general form, with an explicit package name, the import\n-statement declares that package name as an identifier whose\n-contents are the exported elements of the imported package.\n-For instance, after\n+In this table, assume we have compiled a package named\n+<code>math</code>, which exports function <code>Sin</code>, and\n+installed the compiled package in file\n+<code>"lib/math"</code>.\n+</p>\n \n-<pre>\n-import M "/lib/math"\n+<pre class=\"grammar\">\n+Import syntax               Local name of Sin\n+\n+import M "lib/math"         M.Sin\n+import   "lib/math"         math.Sin\n+import . "lib/math"         Sin\n </pre>

インポート宣言に関する説明が大幅に拡張され、特に異なるインポート形式がどのように識別子のアクセスに影響するかについて、詳細な説明と具体的な例が追加されました。エイリアス付きインポート、パッケージ名省略インポート、ドットインポートのそれぞれの挙動が明確に示されており、Goのインポートメカニズムの柔軟性と、それに伴う名前解決のルールが理解しやすくなっています。

複数ファイルパッケージの説明の追加

+<h3>Multi-file packages</h3>
+\n <p>\n+If a package is constructed from multiple source files, all names\n+at package-level scope, not just exported names, are visible to all the\n+files in the package. An import declaration is still necessary to\n+declare intention to use the names,\n+but the imported names do not need a qualified identifer to be\n+accessed.\n+</p>\n \n+<p>\n+The compilation of a multi-file package may require\n+that the files be compiled and installed in an order that satisfies\n+the resolution of names imported within the package.\n+</p>\n+\n+<p>\n+If source file <code>math1.go</code> contains\n+</p>\n <pre>\n+package math\n+\n+const twoPi = 6.283185307179586\n+\n+function Sin(x float) float { return ... }\n </pre>\n \n+and file <code>"math2.go"</code> begins\n+</p>\n <pre>\n+package math\n+\n+import "lib/math"\n </pre>\n \n+then, provided <code>"math1.go"</code> is compiled first and\n+installed in <code>"lib/math"</code>, <code>math2.go</code>\n+may refer directly to <code>Sin</code> and <code>twoPi</code>\n+without a qualified identifier.\n+</p>

複数ファイルからなるパッケージの概念が導入され、同じパッケージ内のファイル間では、エクスポートされているかどうかにかかわらず、すべてのパッケージレベルの識別子が可視であることが説明されています。これは、Goのパッケージが単一のコンパイル単位として扱われることを示しており、大規模なプロジェクトでのコード分割と管理の基礎となります。

素数篩の例の更新

-print(prime, "\n");
+fmt.Print(prime, "\n");
+import "fmt"

print 関数が fmt.Print に変更され、fmt パッケージがインポートされるようになりました。これは、Go言語の標準ライブラリの進化に合わせて、ドキュメント内のコード例が更新されたことを示しています。初期のGoでは組み込みの print が存在しましたが、より柔軟で機能豊富な fmt パッケージが標準的なI/O操作のために推奨されるようになりました。

4. main.main() の説明の修正

-When main.main() returns, the program exits.
+When <code>main.main()</code> returns, the program exits.

main.main() がコードブロックとしてマークアップされるように修正されています。これは、ドキュメントのフォーマットと可読性を向上させるための小さな変更です。

これらの変更は、Go言語のパッケージシステムが初期段階でどのように設計され、ドキュメント化されていったかを示す貴重な証拠です。特に、パッケージの構造、インポートのセマンティクス、複数ファイルパッケージの概念が、言語の核となる部分としてどのように確立されていったかが詳細に記述されています。

関連リンク

参考にした情報源リンク