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

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

このコミットは、Go言語の公式仕様書である doc/go_spec.html ファイルに対する変更です。具体的には、組み込み関数 append の呼び出し構文に関する記述の修正と、Goの反射(reflection)に関するリンクの修正、そして仕様書自体のバージョン日付の更新が含まれています。

コミット

  • コミットハッシュ: 458632a21a7e532e10b7a64daf447e2ccfab97e1
  • 作者: Robert Griesemer gri@golang.org
  • コミット日時: 2012年12月4日 火曜日 13:09:02 -0800

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

https://github.com/golang/go/commit/458632a21a7e532e10b7a64daf447e2ccfab97e1

元コミット内容

spec: BuiltinCall syntax must permit "..." for append

Also: fix an incorrect link.

Fixes #4479.
Fixes #4456.

R=rsc, iant, r, ken
CC=golang-dev
https://golang.org/cl/6868062

変更の背景

このコミットは、Go言語の仕様書における2つの主要な問題を修正するために行われました。

  1. append 関数の可変引数(variadic arguments)の記述の不備(Fixes #4479): Go言語の組み込み関数 append は、スライスに要素を追加するために使用されます。この関数は、追加する要素を個別に指定することも、別のスライスを展開して追加することもできます。後者の場合、... (エリプシス) 演算子を使用してスライスを展開します。しかし、当時のGo仕様書における BuiltinCall の構文定義では、この ... 演算子を用いた append の呼び出し形式が明示的に許可されていませんでした。これは仕様と実際の言語動作との乖離を生んでおり、このコミットによって仕様が実際の動作に合致するように修正されました。

  2. 反射インターフェースへのリンクの誤り(Fixes #4456): Go言語には、実行時に型情報を検査・操作するための「反射(reflection)」機能があります。構造体のフィールドに付与されるタグ(tag)は、この反射インターフェースを通じてアクセス可能ですが、仕様書内の関連リンクが Package_unsafe という誤ったアンカー(または古いパッケージ名)を指していました。正しいリンクは reflect パッケージ内の StructTag 型を指すべきであり、このコミットで修正されました。

これらの修正は、Go言語の仕様書が言語の正確な動作を反映し、開発者にとって信頼できる情報源であることを保証するために重要です。

前提知識の解説

Go言語の仕様書 (doc/go_spec.html)

Go言語の仕様書は、Go言語の構文、セマンティクス、および組み込み機能の公式な定義を提供する文書です。Go言語の設計と実装の基礎となるものであり、コンパイラやツールの開発者、そして言語の深い理解を求めるプログラマにとって不可欠なリファレンスです。このファイルはHTML形式で記述されており、ウェブブラウザで閲覧可能です。

Go言語の組み込み関数 (append)

Go言語には、言語に組み込まれた特別な関数がいくつかあります。これらは通常、特定の型に依存しない汎用的な操作を提供します。append はその一つで、スライスに要素を追加するために使用されます。

func append(slice []Type, elems ...Type) []Type

append は、最初の引数としてスライスを受け取り、その後に0個以上の要素(elems)を受け取ります。elems が別のスライスである場合、そのスライスを ... 演算子で展開して渡すことができます。

例:

s1 := []int{1, 2}
s2 := []int{3, 4}

// 個別の要素を追加
s1 = append(s1, 5, 6) // s1 は {1, 2, 5, 6}

// スライスを展開して追加
s1 = append(s1, s2...) // s1 は {1, 2, 5, 6, 3, 4}

可変引数(Variadic Arguments)と ... 演算子

Go言語の関数は、最後のパラメータに ... を付けることで、可変個の引数を受け取ることができます。これを可変引数関数と呼びます。関数内で可変引数はスライスとして扱われます。

また、関数呼び出しの際にスライスを可変引数パラメータに渡す場合にも ... 演算子を使用します。これにより、スライスの各要素が個別の引数として関数に渡されます。

Go言語の反射(Reflection)と reflect.StructTag

Goの反射は、プログラムが自身の構造を検査する能力です。これにより、実行時に変数の型、値、構造体のフィールドなどを調べたり、動的に関数を呼び出したりすることができます。

reflect.StructTag は、構造体のフィールド宣言に付与されるオプションの文字列リテラル(タグ)を表す型です。このタグは、JSONエンコーディングやデータベースマッピングなど、様々な目的でメタデータとして使用されます。reflect パッケージを通じて、これらのタグにアクセスし、その内容を解析することができます。

例:

type User struct {
    Name string `json:"user_name"`
    Age  int    `json:"user_age"`
}

上記の例では、Name フィールドに json:"user_name" というタグが付与されています。このタグは reflect パッケージを使って実行時に読み取ることができます。

EBNF (Extended Backus-Naur Form)

EBNFは、プログラミング言語の構文を記述するためのメタ言語です。Go言語の仕様書でも、言語の構文規則を定義するためにEBNFが使用されています。

例:

BuiltinCall = identifier "(" [ BuiltinArgs [ "," ] ] ")" .

これは、「BuiltinCall は、識別子、その後に括弧で囲まれたオプションの BuiltinArgs(その後にオプションのカンマが続く)で構成される」という構文規則を示しています。

技術的詳細

このコミットは、Go言語の仕様書における2つの異なるセ文脈での修正を含んでいます。

  1. append 関数の ... 構文の明示的な許可: Go言語の append 関数は、スライスを可変引数として受け取る際に ... 演算子を使用します。しかし、Go仕様書の BuiltinCall のEBNF定義では、BuiltinArgsType [ "," ExpressionList ] | ExpressionList となっていました。ここで ExpressionList は単なる式のリストを意味し、... を用いたスライスの展開を明示的に含んでいませんでした。 この修正では、BuiltinArgs の定義を Type [ "," ArgumentList ] | ArgumentList に変更しています。ここで ArgumentList は、Go言語の関数呼び出しにおける引数のリストをより正確に表現するものであり、... 演算子によるスライスの展開も含む概念です。これにより、append(s, otherSlice...) のような呼び出しが仕様上も正当であることが明確になりました。これは、Go言語の進化と、仕様が実際の言語機能に追従することの重要性を示しています。

  2. 反射インターフェースへのリンク修正: 以前の仕様書では、構造体タグが反射インターフェースを通じて可視化されることについて、<a href="#Package_unsafe">reflection interface</a> というリンクが張られていました。これは unsafe パッケージへの参照を示唆していましたが、構造体タグの読み取りは reflect パッケージの機能であり、unsafe パッケージとは直接関係ありません。 この修正により、リンクは <a href="/pkg/reflect/#StructTag">reflection interface</a> に変更されました。これは、Goの標準ライブラリドキュメントにおける reflect パッケージの StructTag 型への直接リンクであり、より正確で有用な情報を提供します。

  3. 仕様書の日付更新: コミットが行われた日付に合わせて、仕様書のサブタイトルにあるバージョン日付が「Version of December 3, 2012」から「Version of December 4, 2012」に更新されました。これは、仕様書が常に最新の状態であることを示すための一般的なメンテナンス作業です。

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

--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
 <!--{
 	"Title": "The Go Programming Language Specification",
-\t"Subtitle": "Version of December 3, 2012",
+\t"Subtitle": "Version of December 4, 2012",
 	"Path": "/ref/spec"
 }-->
 
@@ -1013,7 +1013,7 @@ promoted methods are included in the method set of the struct as follows:\n A field declaration may be followed by an optional string literal <i>tag</i>,\n which becomes an attribute for all the fields in the corresponding\n field declaration. The tags are made\n-visible through a <a href=\"#Package_unsafe\">reflection interface</a>\n+visible through a <a href=\"/pkg/reflect/#StructTag\">reflection interface</a>\n but are otherwise ignored.\n </p>\n \n@@ -4831,7 +4831,7 @@ they cannot be used as function values.\n \n <pre class=\"ebnf\">\n BuiltinCall = identifier \"(\" [ BuiltinArgs [ \",\" ] ] \")\" .\n-BuiltinArgs = Type [ \",\" ExpressionList ] | ExpressionList .\n+BuiltinArgs = Type [ \",\" ArgumentList ] | ArgumentList .\n </pre>\n 

コアとなるコードの解説

1. 仕様書の日付更新

-\t"Subtitle": "Version of December 3, 2012",
+\t"Subtitle": "Version of December 4, 2012",

これは、Go言語の仕様書のサブタイトルに表示される日付を、コミットが行われた2012年12月4日に更新したものです。これは文書のバージョン管理の一環であり、最新の変更が反映されたことを示します。

2. 反射インターフェースへのリンク修正

-visible through a <a href=\"#Package_unsafe\">reflection interface</a>
+visible through a <a href=\"/pkg/reflect/#StructTag\">reflection interface</a>

この変更は、構造体タグが反射を通じて可視化されることに関する説明文中のハイパーリンクを修正しています。

  • 変更前: #Package_unsafe は、unsafe パッケージ内のアンカーを指していました。これは、構造体タグのアクセスが unsafe パッケージの機能であるかのような誤解を与える可能性がありました。
  • 変更後: /pkg/reflect/#StructTag は、Goの標準ライブラリドキュメントにおける reflect パッケージの StructTag 型への直接リンクです。これにより、開発者は構造体タグの正しい利用方法と、それらが reflect パッケージを通じてどのようにアクセスされるかを正確に理解できます。

3. BuiltinCall 構文の修正

 BuiltinCall = identifier \"(\" [ BuiltinArgs [ \",\" ] ] \")\" .\n-BuiltinArgs = Type [ \",\" ExpressionList ] | ExpressionList .\n+BuiltinArgs = Type [ \",\" ArgumentList ] | ArgumentList .\n```
この変更は、Go言語の組み込み関数呼び出し(`BuiltinCall`)の引数(`BuiltinArgs`)に関するEBNF構文定義を修正しています。
-   **変更前**: `BuiltinArgs = Type [ "," ExpressionList ] | ExpressionList .`
    この定義では、組み込み関数の引数が `Type` と `ExpressionList`(式のリスト)の組み合わせ、または単なる `ExpressionList` であるとされていました。`ExpressionList` は、`append(s, x, y)` のように個々の要素を渡す場合には適切ですが、`append(s, otherSlice...)` のようにスライスを展開して渡す形式を明示的にカバーしていませんでした。
-   **変更後**: `BuiltinArgs = Type [ "," ArgumentList ] | ArgumentList .`
    `ExpressionList` が `ArgumentList` に置き換えられました。Go言語の文脈において、`ArgumentList` は関数呼び出しにおける引数のより包括的な概念であり、これには可変引数としてスライスを展開する `...` 演算子を用いた形式も含まれます。この修正により、`append` 関数がスライスを可変引数として受け取る際の構文が、仕様上も正確に記述されるようになりました。これは、Go言語の仕様が実際の言語の動作と一致するように更新された重要な点です。

## 関連リンク

*   Go言語の公式仕様書: [https://go.dev/ref/spec](https://go.dev/ref/spec)
*   Go言語 `append` 関数ドキュメント: [https://go.dev/pkg/builtin/#append](https://go.dev/pkg/builtin/#append)
*   Go言語 `reflect` パッケージ `StructTag` ドキュメント: [https://go.dev/pkg/reflect/#StructTag](https://go.dev/pkg/reflect/#StructTag)
*   Go Change List 6868062: [https://golang.org/cl/6868062](https://golang.org/cl/6868062)
*   Go Issue #4479: spec: BuiltinCall syntax must permit "..." for append: [https://go.dev/issue/4479](https://go.dev/issue/4479)
*   Go Issue #4456: doc: fix incorrect link to reflection interface: [https://go.dev/issue/4456](https://go.dev/issue/4456)

## 参考にした情報源リンク

*   Go言語の公式ドキュメント (上記「関連リンク」に記載)
*   Go言語のGitHubリポジトリ (コミット履歴とIssueトラッカー)
*   EBNF (Extended Backus-Naur Form) の一般的な情報源 (例: Wikipedia)
*   Go言語における可変引数と `...` 演算子に関する解説記事 (一般的なGoプログラミングのチュートリアルやブログ記事)