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

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

このコミットは、Go言語の公式ドキュメントの一部である doc/go1.html および doc/go1.tmpl ファイルに対する更新です。具体的には、Go 1リリースにおける主要な変更点について、その背景や正当性を説明する議論(justification discussions)が追加されています。これにより、Go 1で導入された言語仕様や標準ライブラリの変更がなぜ行われたのか、その意図がより明確に伝えられるようになります。

コミット

commit 68c7e8a2f431577e77273f1860f3f88dc06627ea
Author: Rob Pike <r@golang.org>
Date:   Mon Feb 27 07:31:34 2012 +1100

    doc/go1: add justification discussions to major changes
    
    Fixes #3086.
    
    R=golang-dev, gri, r, kevlar
    CC=golang-dev
    https://golang.org/cl/5700067

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

https://github.com/golang/go/commit/68c7e8a2f431577e77273f1860f3f88dc06627ea

元コミット内容

このコミットは、Go 1リリースノートのドキュメント (doc/go1.htmldoc/go1.tmpl) に、Go 1で導入された主要な変更点に関する「正当化の議論(justification discussions)」を追加するものです。これは、単に機能が変更されたことを記述するだけでなく、なぜその変更が必要だったのか、どのような問題が解決されたのか、といった背景情報を提供することを目的としています。

具体的には、以下の項目について説明が追加されています。

  • append 関数
  • close 関数
  • init 時のGoroutineの挙動
  • rune 型の導入
  • マップからの要素削除 (delete 関数)
  • マップのイテレーション順序のランダム化
  • 多重代入の評価順序
  • シャドーイングされた変数とreturn
  • エクスポートされていないフィールドを持つ構造体のコピー
  • 構造体と配列の等価性比較
  • error型とerrorsパッケージ
  • システムコールエラー (syscallパッケージ)
  • timeパッケージの再設計
  • その他の小さな変更点(archive/zip, encoding/xml, go/docなど)

変更の背景

Go 1はGo言語の最初の安定版リリースであり、将来にわたる互換性を保証するための重要なマイルストーンでした。このリリースでは、言語の設計を洗練し、標準ライブラリを改善するために多くの変更が導入されました。しかし、これらの変更は既存のコードベースに影響を与える可能性があり、開発者がGo 1への移行をスムーズに行えるように、変更の理由と影響を明確に説明する必要がありました。

このコミットの背景には、Go 1の設計思想、特に「シンプルさ」「安全性」「パフォーマンス」といった原則があります。例えば、init時のGoroutineの挙動変更は、初期化処理の柔軟性と安全性を向上させるため、rune型の導入はUnicode文字の適切な処理と将来的なint型の64ビット化を可能にするため、マップのイテレーション順序のランダム化は、開発者が意図しない順序依存のコードを書くことを防ぐため、といった具体的な理由が存在します。

このコミットは、これらの重要な変更が単なる恣意的なものではなく、明確な設計上の理由と利点に基づいていることを開発者に理解してもらうためのドキュメント改善の一環として行われました。

前提知識の解説

このコミットの変更内容を理解するためには、Go言語の基本的な概念と、Go 1リリース以前のGo言語(r60.3など)の挙動に関する知識が役立ちます。

  • Go言語の基本: Goroutine、チャネル、スライス、マップ、構造体、インターフェース、パッケージといったGo言語の基本的なデータ構造と並行処理の概念。
  • append関数: スライスに要素を追加するための組み込み関数。
  • close関数: チャネルを閉じるための組み込み関数。
  • init関数: パッケージの初期化時に自動的に実行される関数。
  • rune: Go言語におけるUnicodeコードポイントを表す型。Go 1以前はint型がUnicodeコードポイントを表すために使われることが多かった。
  • マップ: キーと値のペアを格納するデータ構造。Go 1以前はマップのイテレーション順序が定義されていなかった。
  • 多重代入: 複数の変数に同時に値を代入するGoの機能。
  • シャドーイング: 内側のスコープで外側のスコープの変数と同じ名前の変数を宣言すること。
  • エクスポートされていないフィールド: Go言語では、フィールド名が小文字で始まる場合、そのフィールドはパッケージ外からアクセスできない(エクスポートされていない)。
  • 等価性比較: ==および!=演算子による値の比較。Go 1以前は構造体や配列の等価性比較が定義されていなかった。
  • errorインターフェース: Go言語におけるエラー処理の標準的なインターフェース。Go 1以前はos.Error型が使われることが多かった。
  • syscallパッケージ: オペレーティングシステムのシステムコールにアクセスするためのパッケージ。
  • timeパッケージ: 時間と日付を扱うための標準ライブラリパッケージ。

これらの概念について、Go 1以前の挙動とGo 1での変更点を比較することで、このコミットが追加した「正当化の議論」の意義を深く理解できます。

技術的詳細

このコミットは、doc/go1.htmldoc/go1.tmplという2つのドキュメントファイルを変更しています。これらのファイルは、Go 1のリリースノートを生成するためのソースであり、HTMLとGoのテンプレート構文を組み合わせて記述されています。

変更の主な内容は、既存の各セクションに新たな<p>タグで囲まれた段落を追加し、Go 1での変更がなぜ行われたのか、その技術的な理由や設計上の考慮事項を詳細に説明することです。

以下に、いくつかの主要な変更点とその技術的詳細の追加内容を抜粋して解説します。

append関数

  • 変更前: appendは可変引数関数であり、バイトスライスにバイトを追加する際に...構文を使用できた。しかし、文字列を[]byteに直接追加する方法がなかった。
  • 追加された説明: appendはバイトスライスに文字列をバイト単位で直接追加できるようになり、変換が不要になった。これにより、文字列とバイトスライスの間の摩擦が軽減された。

close関数

  • 変更前: closeはチャネルの送信者がこれ以上データを送信しないことを受信者に伝えるための組み込み関数。Go 1以前は、closeが正しく使用されているか(例えば、受信専用チャネルに対してcloseが呼び出されていないか)のコンパイル時チェックがなかった。
  • 追加された説明: closeは送信側のゴルーチンのみが使用することを意図しており、受信専用チャネルに対するcloseの呼び出しはコンパイル時エラーとなるように変更された。これにより、誤用や競合状態を防ぐ。

init時のGoroutine

  • 変更前: 以前の言語仕様では、初期化中に実行されるgoステートメントはゴルーチンを作成するが、プログラム全体の初期化が完了するまで実行を開始しなかった。これは、initの有用性を制限し、ライブラリが初期化中にゴルーチンを使用することを避ける必要があった。
  • 追加された説明: Go 1では、初期化中にゴルーチンが作成され、すぐに実行されるようになった。これにより、initルーチンやグローバル初期化式からゴルーチンを使用してもデッドロックが発生せず、initの柔軟性が向上した。これは、言語に対する信頼が高まった結果、以前の設計が不必要であると判断されたため。

rune

  • 変更前: 以前の言語仕様ではint型が32ビットまたは64ビット幅を許容していたが、当時の実装では64ビットプラットフォームでもintは32ビットだった。Unicodeコードポイントもintで保持されていたため、intが64ビットに拡張されると、各コードポイントが余分な32ビットのストレージを浪費する問題があった。
  • 追加された説明: 64ビットintへの変更を可能にするため、Go 1では個々のUnicodeコードポイントを表す新しい基本型runeが導入された。runeint32のエイリアスであり、byteuint8のエイリアスであるのと同様。これにより、intのサイズ変更がUnicode処理に与える影響を分離できる。

マップからの要素削除 (delete関数)

  • 変更前: マップから要素を削除する構文はm[k] = value, falseという特殊な形式だった。これは、評価されるが破棄される値と、ほとんど常にfalseであるブール値を渡す必要があり、奇妙で議論の的となっていた。
  • 追加された説明: Go 1では、この構文が廃止され、新しい組み込み関数delete(m, k)が導入された。これにより、マップからの要素削除がより直感的で明確になった。

マップのイテレーション順序

  • 変更前: 以前の言語仕様では、マップのイテレーション順序が定義されておらず、ハードウェアプラットフォームによって異なる可能性があった。これにより、マップのイテレーションに依存するテストが不安定で移植性が低いものとなっていた。
  • 追加された説明: Go 1では、for rangeステートメントでマップをイテレートする際の要素の訪問順序が意図的にランダム化された。これにより、開発者がイテレーション順序に依存するコードを書くことを防ぎ、早期にバグを発見できるようにする。また、マップの実装がより良いバランスを確保できるようになる。

構造体と配列の等価性

  • 変更前: Go 1以前は、構造体と配列の値の等価性が定義されていなかった。これにより、構造体や配列をマップのキーとして使用できなかった。また、関数やマップの等価性比較は定義されていたが、関数はクロージャの存在下で問題があり、マップは内容ではなくポインタを比較するため、ユーザーの意図と異なることが多かった。
  • 追加された説明: Go 1では、構造体と配列の値の等価性比較(==!=)が定義され、それらがマップのキーとして使用できるようになった。ただし、比較可能な要素で構成されている場合に限る。また、関数値の等価性定義はnilとの比較を除いて削除され、マップの等価性もnilとの比較を除いて削除された。

これらの変更は、Go言語の設計原則に基づき、言語の一貫性、安全性、使いやすさを向上させることを目的としています。

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

このコミットは、Go言語のソースコード自体ではなく、Go 1リリースに関するドキュメントのHTMLおよびテンプレートファイルを変更しています。

  • doc/go1.html
  • doc/go1.tmpl

これらのファイルは、Go 1の主要な変更点について説明する公式ドキュメントのコンテンツを構成しています。変更は主に、既存のセクションに新たな段落(<p>タグで囲まれたテキスト)を追加し、各変更の「正当化の議論」を挿入する形で行われています。

例: append関数に関する変更

--- a/doc/go1.html
+++ b/doc/go1.html
@@ -57,9 +57,11 @@ r60.3). It also explains how to update code from r60 to run under Go 1.
 <h3 id="append">Append</h3>
 
 <p>
-The <code>append</code> built-in function is variadic, so one can
-append to a byte slice using the <code>...</code> syntax in the
-call.
+The <code>append</code> predeclared variadic function makes it easy to grow a slice
+by adding elements to the end.
+A common use is to add bytes to the end of a byte slice when generating output.
+However, <code>append</code> did not provide a way to append a string to a <code>[]byte</code>,
+which is another common case.
 </p>
 
 <pre><!--{{code "progs/go1.go" `/greeting := ..byte/` `/append.*hello/`}}
@@ -69,7 +71,8 @@ call.
 <p>
 By analogy with the similar property of <code>copy</code>, Go 1
 permits a string to be appended (byte-wise) directly to a byte
-slice; the conversion is no longer necessary:\n+slice, reducing the friction between strings and byte slices.\n+The conversion is no longer necessary:
 </p>

この差分は、append関数に関する説明に、文字列をバイトスライスに直接追加できなかったという以前の課題と、Go 1でそれが可能になったことで「文字列とバイトスライスの間の摩擦が軽減された」という正当化の議論が追加されていることを示しています。

同様の変更が、closeinit時のGoroutine、rune型、マップの削除、マップのイテレーション、多重代入、シャドーイング、構造体のコピー、等価性、エラー処理、システムコール、時間パッケージなど、Go 1の主要な変更点に関するすべてのセクションで行われています。

コアとなるコードの解説

このコミットにおける「コアとなるコード」は、Go 1のリリースノートを構成するHTMLドキュメントとテンプレートファイルです。これらのファイルは、Go言語の変更点とその理由を説明するための情報源として機能します。

変更の目的は、Go 1で導入された各機能や仕様変更について、単に「何が変わったか」だけでなく、「なぜ変わったのか」という背景と正当性を明確にすることです。これにより、Go言語の設計思想と進化の過程を開発者がより深く理解できるようになります。

例えば、マップのイテレーション順序がランダム化されたことについて、このコミットで追加された説明は、以前の挙動がプラットフォーム間で異なり、テストの不安定性や移植性の問題を引き起こしていたことを指摘しています。そして、Go 1でのランダム化は、開発者が意図せずイテレーション順序に依存するコードを書くことを防ぎ、早期にバグを発見できるようにするという設計上の意図を明確にしています。

このように、各変更点に対して、問題提起、Go 1での解決策、そしてその解決策がもたらす利点や設計上の考慮事項が詳細に記述されています。これは、Go言語の透明性と、開発者コミュニティへの情報提供の姿勢を示すものです。

関連リンク

参考にした情報源リンク

  • コミットメッセージと差分情報 (./commit_data/12216.txt)
  • Go言語の公式ドキュメント (Go 1 Release Notes)
  • Go言語の設計に関する一般的な知識