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

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

このコミットは、Go言語の公式仕様書である doc/go_spec.html ファイルに対する変更です。具体的には、関数やメソッドのレシーバ、パラメータ、および結果の変数名に関する命名規則、特に一意性(ユニークネス)の要件を明確化し、関連するスコープの記述を修正しています。

コミット

commit 85e451e2fe3aae0c5d066cd0ee5f178877139188
Author: Robert Griesemer <gri@golang.org>
Date:   Thu Nov 29 14:47:47 2012 -0800

    go spec: receiver, parameter, and result names must always be unique

    Fixes #4450.

    R=rsc, iant
    CC=golang-dev
    https://golang.org/cl/6845104

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

https://github.com/golang/go/commit/85e451e2fe3aae0c5d066cd0ee5f178877139188

元コミット内容

go spec: receiver, parameter, and result names must always be unique

Fixes #4450.

R=rsc, iant
CC=golang-dev
https://golang.org/cl/6845104

変更の背景

このコミットは、Go言語の仕様におけるレシーバ、パラメータ、および結果の変数名の一意性に関する曖昧さを解消するために行われました。特に、Go言語のIssue #4450("go spec: parameter and result names must be unique")で報告された問題に対応しています。

Go言語では、関数やメソッドのシグネチャにおいて、パラメータや結果に名前を付けることができます。しかし、これらの名前が重複した場合の挙動や、仕様上の明確な規定が不足していました。例えば、同じ関数内でパラメータ名と結果名が重複したり、複数のパラメータが同じ名前を持ったりするケースです。このような曖昧さは、コンパイラの挙動の一貫性を損ねたり、開発者が混乱したりする原因となります。

このコミットの目的は、Go言語の仕様書を更新し、レシーバ、パラメータ、および結果の非ブランク識別子(_ ではない名前)が、そのシグネチャ内で常に一意でなければならないというルールを明示的に記述することです。これにより、言語の定義がより厳密になり、コンパイラの実装やコードの解釈における一貫性が保証されます。

前提知識の解説

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

  1. Go言語の仕様書 (Go Spec): Go言語の公式な動作を定義する文書です。コンパイラやツールは、この仕様書に基づいて実装されます。
  2. 関数シグネチャ (Function Signature): 関数の名前、パラメータのリスト、および結果のリストを含む、関数の型を定義する部分です。メソッドの場合は、レシーバも含まれます。 例: func (r MyType) MyMethod(param1 int, param2 string) (result1 bool, result2 error)
  3. レシーバ (Receiver): メソッドがどの型に属するかを示すために、メソッド宣言の関数名の前に記述される特別なパラメータです。 例: (r MyType)r
  4. パラメータ (Parameters): 関数やメソッドに渡される引数を受け取る変数です。 例: (param1 int, param2 string)param1param2
  5. 結果 (Results): 関数やメソッドが返す値を受け取る変数です。Goでは、結果にも名前を付けることができます(名前付き戻り値)。 例: (result1 bool, result2 error)result1result2
  6. ブランク識別子 (Blank Identifier): Go言語における特別な識別子で、アンダースコア _ で表されます。ブランク識別子は、値を破棄するために使用され、宣言されたスコープ内で一意である必要はありません。これは、意図的に使用されない変数やインポートを示すために使われます。
  7. 識別子の一意性 (Uniqueness of Identifiers): プログラミング言語において、同じスコープ内で同じ名前の変数を複数宣言できないという規則です。これにより、どの変数を参照しているのかが明確になります。
  8. スコープ (Scope): 識別子(変数、関数、型など)が有効であるプログラムの領域です。Go言語では、ブロック、ファイル、パッケージなど、様々なスコープが存在します。

このコミットは、特にレシーバ、パラメータ、結果の名前が「非ブランク識別子」である場合に、そのシグネチャ内で「一意」でなければならないという点を強調しています。

技術的詳細

このコミットの技術的な核心は、Go言語の仕様書 doc/go_spec.html 内の複数のセクションを更新し、レシーバ、パラメータ、および結果の命名に関する厳格なルールを導入した点にあります。

主な変更点は以下の通りです。

  1. パラメータおよび結果リストの一意性:

    • 変更前は、パラメータや結果のリストにおいて名前が指定されている場合、各名前が指定された型の1つの項目を表すという記述のみでした。
    • 変更後は、「非ブランク識別子であるすべての名前は、シグネチャ内で一意でなければならない」という明確な制約が追加されました。これにより、例えば func foo(x int, x string) のような宣言や、func bar() (x int, x string) のような宣言が不正であることが明示されます。
  2. スコープの明確化:

    • 変更前は、「関数パラメータまたは結果変数を表す識別子のスコープは関数本体である」と記述されていました。
    • 変更後は、「メソッドレシーバ、関数パラメータ、または結果変数を表す識別子のスコープは関数本体である」と修正され、メソッドレシーバもこのスコープ規則に含まれることが明示されました。これは、レシーバも関数本体内で通常のローカル変数と同様に扱われることを意味します。
  3. レシーバ識別子の一意性:

    • メソッドのレシーバに関するセクションに、新しい段落が追加されました。「非ブランクのレシーバ識別子は、メソッドシグネチャ内で一意でなければならない」というルールが明記されました。
    • また、レシーバの値がメソッド本体内で参照されない場合、その識別子を宣言で省略できるという既存のルールが、この新しい一意性のルールと並列して記述されるように再構成されました。これは、パラメータについても同様に適用されます。

これらの変更は、Go言語のコンパイラが、レシーバ、パラメータ、結果の名前の重複をエラーとして検出するための明確な根拠を提供します。これにより、言語の定義がより堅牢になり、開発者がより予測可能なコードを書けるようになります。

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

変更は doc/go_spec.html ファイルに対して行われています。

  1. ParameterDecl セクション (約1065行目):

    --- a/doc/go_spec.html
    +++ b/doc/go_spec.html
    @@ -1065,8 +1065,11 @@ ParameterDecl  = [ IdentifierList ] [ "..." ] Type .
     <p>
     Within a list of parameters or results, the names (IdentifierList)
     must either all be present or all be absent. If present, each name
    -stands for one item (parameter or result) of the specified type; if absent, each
    -type stands for one item of that type.  Parameter and result
    +stands for one item (parameter or result) of the specified type and
    +all non-<a href="#Blank_identifier">blank</a> names in the signature
    +must be <a href="#Uniqueness_of_identifiers">unique</a>.
    +If absent, each type stands for one item of that type.
    +Parameter and result
     lists are always parenthesized except that if there is exactly
     one unnamed result it may be written as an unparenthesized type.
     </p>
    
    • all non-blank names in the signature must be unique. が追加されました。
  2. スコープの定義セクション (約1532行目):

    --- a/doc/go_spec.html
    +++ b/doc/go_spec.html
    @@ -1532,8 +1535,8 @@ Go is lexically scoped using blocks:
      	<li>The scope of the package name of an imported package is the file block
      	    of the file containing the import declaration.</li>
    
    -\t<li>The scope of an identifier denoting a function parameter or
    -\t    result variable is the function body.</li>
    +\t<li>The scope of an identifier denoting a method receiver, function parameter,
    +\t    or result variable is the function body.</li>
    
      	<li>The scope of a constant or variable identifier declared
      	    inside a function begins at the end of the ConstSpec or VarSpec
    
    • method receiver, が追加され、レシーバもスコープの定義に含まれるようになりました。
  3. メソッドの定義セクション (約1988行目):

    --- a/doc/go_spec.html
    +++ b/doc/go_spec.html
    @@ -1988,8 +1991,15 @@ is visible only within selectors for that type.\n </p>\n \n <p>\n-For a base type, the non-<a href=\"#Blank_identifier\">blank</a> names of\n-methods bound to it must be <a href=\"#Uniqueness_of_identifiers\">unique</a>.\n+A non-<a href=\"#Blank_identifier\">blank</a> receiver identifier must be\n+<a href=\"#Uniqueness_of_identifiers\">unique</a> in the method signature.\n+If the receiver\'s value is not referenced inside the body of the method,\n+its identifier may be omitted in the declaration. The same applies in\n+general to parameters of functions and methods.\n+</p>\n+\n+<p>\n+For a base type, the non-blank names of methods bound to it must be unique.\n If the base type is a <a href=\"#Struct_types\">struct type</a>,\n the non-blank method and field names must be distinct.\n </p>\n@@ -2015,12 +2025,6 @@ with receiver type <code>*Point</code>,\n to the base type <code>Point</code>.\n </p>\n \n-<p>\n-If the receiver\'s value is not referenced inside the body of the method,\n-its identifier may be omitted in the declaration. The same applies in\n-general to parameters of functions and methods.\n-</p>\n-\n <p>\n The type of a method is the type of a function with the receiver as first\n argument.  For instance, the method <code>Scale</code> has type\n    ```
    - レシーバ識別子の一意性に関する新しい段落が追加されました。
    - 以前のレシーバ識別子の省略に関する段落が削除され、新しい段落に統合されました。
    
    
  4. return ステートメントのセクション (約4599行目):

    --- a/doc/go_spec.html
    +++ b/doc/go_spec.html
    @@ -4599,7 +4603,7 @@ func complexF2() (re float64, im float64) {\n </pre>\n \t</li>\n \t<li>The expression list may be empty if the function\'s result\n-\t\ttype specifies names for its result parameters (§<a href=\"#Function_types\">Function Types</a>).\n+\t\ttype specifies names for its result parameters (§<a href=\"#Function_types\">Function types</a>).\n \t\tThe result parameters act as ordinary local variables\n \t\tand the function may assign values to them as necessary.\n \t\tThe "return" statement returns the values of these variables.\n    ```
    - リンクテキストの表記が "Function Types" から "Function types" に修正されました(大文字小文字の変更)。
    
    

コアとなるコードの解説

このコミットの「コード」はGo言語の仕様書(HTML形式)であり、プログラミング言語のソースコードではありません。したがって、「コアとなるコードの解説」は、変更された仕様書のテキストがGo言語のセマンティクスに与える影響に焦点を当てます。

最も重要な変更は、パラメータ、結果、およびレシーバの非ブランク識別子に一意性制約を課した点です。

  • ParameterDecl セクションの変更: この変更により、以下のようなコードはGo言語の仕様に違反し、コンパイルエラーとなることが明確になります。

    func example(a int, a string) { // パラメータ名 'a' が重複
        // ...
    }
    
    func namedResults() (x int, x string) { // 結果名 'x' が重複
        // ...
        return
    }
    

    以前は、このようなケースが仕様で明確に禁止されていなかったため、コンパイラの実装によっては挙動が異なる可能性がありました。この変更により、すべてのGoコンパイラがこれらのケースをエラーとして扱うことが保証されます。

  • スコープ定義の変更: レシーバが関数本体のスコープに含まれることが明示されたことで、レシーバ変数も関数本体内で宣言された他のローカル変数と同様に扱われることが強調されます。これは、レシーバ名が関数本体内の他の変数名と衝突してはならないことを意味します。

  • メソッド定義セクションの変更: レシーバ識別子の一意性に関する新しい段落は、メソッド宣言におけるレシーバ名の重要性を強調します。

    type MyType int
    
    func (m MyType) MyMethod(m int) { // レシーバ名 'm' とパラメータ名 'm' が重複
        // ...
    }
    

    このような宣言も、この変更により明確に不正となります。また、レシーバやパラメータが使用されない場合に識別子を省略できるという既存のルールは維持されつつ、一意性ルールとの関係がより明確になりました。

これらの変更は、Go言語の構文解析とセマンティック解析の段階で、より厳密なチェックを可能にし、開発者がより堅牢でエラーの少ないコードを書くことを促します。

関連リンク

  • Go Issue #4450: https://github.com/golang/go/issues/4450 このコミットが修正したGo言語のIssueです。パラメータと結果の名前の一意性に関する議論が含まれています。
  • Go Change List 6845104: https://golang.org/cl/6845104 このコミットに対応するGoのコードレビューシステム(Gerrit)上の変更リストです。

参考にした情報源リンク

このコミットは、Go言語の公式仕様書である doc/go_spec.html ファイルに対する変更です。具体的には、関数やメソッドのレシーバ、パラメータ、および結果の変数名に関する命名規則、特に一意性(ユニークネス)の要件を明確化し、関連するスコープの記述を修正しています。

コミット

commit 85e451e2fe3aae0c5d066cd0ee5f178877139188
Author: Robert Griesemer <gri@golang.org>
Date:   Thu Nov 29 14:47:47 2012 -0800

    go spec: receiver, parameter, and result names must always be unique

    Fixes #4450.

    R=rsc, iant
    CC=golang-dev
    https://golang.org/cl/6845104

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

https://github.com/golang/go/commit/85e451e2fe3aae0c5d066cd0ee5f178877139188

元コミット内容

go spec: receiver, parameter, and result names must always be unique

Fixes #4450.

R=rsc, iant
CC=golang-dev
https://golang.org/cl/6845104

変更の背景

このコミットは、Go言語の仕様におけるレシーバ、パラメータ、および結果の変数名の一意性に関する曖昧さを解消するために行われました。特に、Go言語のIssue #4450("go spec: parameter and result names must be unique")で報告された問題に対応しています。

Go言語では、関数やメソッドのシグネチャにおいて、パラメータや結果に名前を付けることができます。しかし、これらの名前が重複した場合の挙動や、仕様上の明確な規定が不足していました。例えば、同じ関数内でパラメータ名と結果名が重複したり、複数のパラメータが同じ名前を持ったりするケースです。このような曖昧さは、コンパイラの挙動の一貫性を損ねたり、開発者が混乱したりする原因となります。

このコミットの目的は、Go言語の仕様書を更新し、レシーバ、パラメータ、および結果の非ブランク識別子(_ ではない名前)が、そのシグネチャ内で常に一意でなければならないというルールを明示的に記述することです。これにより、言語の定義がより厳密になり、コンパイラの実装やコードの解釈における一貫性が保証されます。

前提知識の解説

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

  1. Go言語の仕様書 (Go Spec): Go言語の公式な動作を定義する文書です。コンパイラやツールは、この仕様書に基づいて実装されます。
  2. 関数シグネチャ (Function Signature): 関数の名前、パラメータのリスト、および結果のリストを含む、関数の型を定義する部分です。メソッドの場合は、レシーバも含まれます。 例: func (r MyType) MyMethod(param1 int, param2 string) (result1 bool, result2 error)
  3. レシーバ (Receiver): メソッドがどの型に属するかを示すために、メソッド宣言の関数名の前に記述される特別なパラメータです。 例: (r MyType)r
  4. パラメータ (Parameters): 関数やメソッドに渡される引数を受け取る変数です。 例: (param1 int, param2 string)param1param2
  5. 結果 (Results): 関数やメソッドが返す値を受け取る変数です。Goでは、結果にも名前を付けることができます(名前付き戻り値)。 例: (result1 bool, result2 error)result1result2
  6. ブランク識別子 (Blank Identifier): Go言語における特別な識別子で、アンダースコア _ で表されます。ブランク識別子は、値を破棄するために使用され、宣言されたスコープ内で一意である必要はありません。これは、意図的に使用されない変数やインポートを示すために使われます。
  7. 識別子の一意性 (Uniqueness of Identifiers): プログラミング言語において、同じスコープ内で同じ名前の変数を複数宣言できないという規則です。これにより、どの変数を参照しているのかが明確になります。
  8. スコープ (Scope): 識別子(変数、関数、型など)が有効であるプログラムの領域です。Go言語では、ブロック、ファイル、パッケージなど、様々なスコープが存在します。

このコミットは、特にレシーバ、パラメータ、結果の名前が「非ブランク識別子」である場合に、そのシグネチャ内で「一意」でなければならないという点を強調しています。

技術的詳細

このコミットの技術的な核心は、Go言語の仕様書 doc/go_spec.html 内の複数のセクションを更新し、レシーバ、パラメータ、および結果の命名に関する厳格なルールを導入した点にあります。

主な変更点は以下の通りです。

  1. パラメータおよび結果リストの一意性:

    • 変更前は、パラメータや結果のリストにおいて名前が指定されている場合、各名前が指定された型の1つの項目を表すという記述のみでした。
    • 変更後は、「非ブランク識別子であるすべての名前は、シグネチャ内で一意でなければならない」という明確な制約が追加されました。これにより、例えば func foo(x int, x string) のような宣言や、func bar() (x int, x string) のような宣言が不正であることが明示されます。
  2. スコープの明確化:

    • 変更前は、「関数パラメータまたは結果変数を表す識別子のスコープは関数本体である」と記述されていました。
    • 変更後は、「メソッドレシーバ、関数パラメータ、または結果変数を表す識別子のスコープは関数本体である」と修正され、メソッドレシーバもこのスコープ規則に含まれることが明示されました。これは、レシーバも関数本体内で通常のローカル変数と同様に扱われることを意味します。
  3. レシーバ識別子の一意性:

    • メソッドのレシーバに関するセクションに、新しい段落が追加されました。「非ブランクのレシーバ識別子は、メソッドシグネチャ内で一意でなければならない」というルールが明記されました。
    • また、レシーバの値がメソッド本体内で参照されない場合、その識別子を宣言で省略できるという既存のルールが、この新しい一意性のルールと並列して記述されるように再構成されました。これは、パラメータについても同様に適用されます。

これらの変更は、Go言語のコンパイラが、レシーバ、パラメータ、結果の名前の重複をエラーとして検出するための明確な根拠を提供します。これにより、言語の定義がより堅牢になり、開発者がより予測可能なコードを書けるようになります。

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

変更は doc/go_spec.html ファイルに対して行われています。

  1. ParameterDecl セクション (約1065行目):

    --- a/doc/go_spec.html
    +++ b/doc/go_spec.html
    @@ -1065,8 +1065,11 @@ ParameterDecl  = [ IdentifierList ] [ "..." ] Type .
     <p>
     Within a list of parameters or results, the names (IdentifierList)
     must either all be present or all be absent. If present, each name
    -stands for one item (parameter or result) of the specified type; if absent, each
    -type stands for one item of that type.  Parameter and result
    +stands for one item (parameter or result) of the specified type and
    +all non-<a href="#Blank_identifier">blank</a> names in the signature
    +must be <a href="#Uniqueness_of_identifiers">unique</a>.
    +If absent, each type stands for one item of that type.
    +Parameter and result
     lists are always parenthesized except that if there is exactly
     one unnamed result it may be written as an unparenthesized type.
     </p>
    
    • all non-blank names in the signature must be unique. が追加されました。
  2. スコープの定義セクション (約1532行目):

    --- a/doc/go_spec.html
    +++ b/doc/go_spec.html
    @@ -1532,8 +1535,8 @@ Go is lexically scoped using blocks:
      	<li>The scope of the package name of an imported package is the file block
      	    of the file containing the import declaration.</li>
    
    -\t<li>The scope of an identifier denoting a function parameter or
    -\t    result variable is the function body.</li>
    +\t<li>The scope of an identifier denoting a method receiver, function parameter,
    +\t    or result variable is the function body.</li>
    
      	<li>The scope of a constant or variable identifier declared
      	    inside a function begins at the end of the ConstSpec or VarSpec
    
    • method receiver, が追加され、レシーバもスコープの定義に含まれるようになりました。
  3. メソッドの定義セクション (約1988行目):

    --- a/doc/go_spec.html
    +++ b/doc/go_spec.html
    @@ -1988,8 +1991,15 @@ is visible only within selectors for that type.\n </p>\n \n <p>\n-For a base type, the non-<a href=\"#Blank_identifier\">blank</a> names of\n-methods bound to it must be <a href=\"#Uniqueness_of_identifiers\">unique</a>.\n+A non-<a href=\"#Blank_identifier\">blank</a> receiver identifier must be\n+<a href=\"#Uniqueness_of_identifiers\">unique</a> in the method signature.\n+If the receiver\'s value is not referenced inside the body of the method,\n+its identifier may be omitted in the declaration. The same applies in\n+general to parameters of functions and methods.\n+</p>\n+\n+<p>\n+For a base type, the non-blank names of methods bound to it must be unique.\n If the base type is a <a href=\"#Struct_types\">struct type</a>,\n the non-blank method and field names must be distinct.\n </p>\n@@ -2015,12 +2025,6 @@ with receiver type <code>*Point</code>,\n to the base type <code>Point</code>.\n </p>\n \n-<p>\n-If the receiver\'s value is not referenced inside the body of the method,\n-its identifier may be omitted in the declaration. The same applies in\n-general to parameters of functions and methods.\n-</p>\n-\n <p>\n The type of a method is the type of a function with the receiver as first\n argument.  For instance, the method <code>Scale</code> has type\n    ```
    - レシーバ識別子の一意性に関する新しい段落が追加されました。
    - 以前のレシーバ識別子の省略に関する段落が削除され、新しい段落に統合されました。
    
    
  4. return ステートメントのセクション (約4599行目):

    --- a/doc/go_spec.html
    +++ b/doc/go_spec.html
    @@ -4599,7 +4603,7 @@ func complexF2() (re float64, im float64) {\n </pre>\n \t</li>\n \t<li>The expression list may be empty if the function\'s result\n-\t\ttype specifies names for its result parameters (§<a href=\"#Function_types\">Function Types</a>).\n+\t\ttype specifies names for its result parameters (§<a href=\"#Function_types\">Function types</a>).\n \t\tThe result parameters act as ordinary local variables\n \t\tand the function may assign values to them as necessary.\n \t\tThe "return" statement returns the values of these variables.\n    ```
    - リンクテキストの表記が "Function Types" から "Function types" に修正されました(大文字小文字の変更)。
    
    

コアとなるコードの解説

このコミットの「コード」はGo言語の仕様書(HTML形式)であり、プログラミング言語のソースコードではありません。したがって、「コアとなるコードの解説」は、変更された仕様書のテキストがGo言語のセマンティクスに与える影響に焦点を当てます。

最も重要な変更は、パラメータ、結果、およびレシーバの非ブランク識別子に一意性制約を課した点です。

  • ParameterDecl セクションの変更: この変更により、以下のようなコードはGo言語の仕様に違反し、コンパイルエラーとなることが明確になります。

    func example(a int, a string) { // パラメータ名 'a' が重複
        // ...
    }
    
    func namedResults() (x int, x string) { // 結果名 'x' が重複
        // ...
        return
    }
    

    以前は、このようなケースが仕様で明確に禁止されていなかったため、コンパイラの実装によっては挙動が異なる可能性がありました。この変更により、すべてのGoコンパイラがこれらのケースをエラーとして扱うことが保証されます。

  • スコープ定義の変更: レシーバが関数本体のスコープに含まれることが明示されたことで、レシーバ変数も関数本体内で宣言された他のローカル変数と同様に扱われることが強調されます。これは、レシーバ名が関数本体内の他の変数名と衝突してはならないことを意味します。

  • メソッド定義セクションの変更: レシーバ識別子の一意性に関する新しい段落は、メソッド宣言におけるレシーバ名の重要性を強調します。

    type MyType int
    
    func (m MyType) MyMethod(m int) { // レシーバ名 'm' とパラメータ名 'm' が重複
        // ...
    }
    

    このような宣言も、この変更により明確に不正となります。また、レシーバやパラメータが使用されない場合に識別子を省略できるという既存のルールは維持されつつ、一意性ルールとの関係がより明確になりました。

これらの変更は、Go言語の構文解析とセマンティック解析の段階で、より厳密なチェックを可能にし、開発者がより堅牢でエラーの少ないコードを書くことを促します。

関連リンク

  • Go Issue #4450: https://github.com/golang/go/issues/4450 このコミットが修正したGo言語のIssueです。パラメータと結果の名前の一意性に関する議論が含まれています。
  • Go Change List 6845104: https://golang.org/cl/6845104 このコミットに対応するGoのコードレビューシステム(Gerrit)上の変更リストです。

参考にした情報源リンク