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

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

このコミットは、Go言語の標準ライブラリにおける大規模な変更セット(チェンジリスト19916)の自動ロールバック(元に戻すこと)です。元の変更はビルドを壊したため、このロールバックが実行されました。具体的には、fmt(フォーマット)、reflect(リフレクション)、strconv(文字列変換)、utf8(UTF-8処理)パッケージに加えられた機能追加や修正が取り消されています。

コミット

commit 85fea81d70d0af531944cc6ceacf955b4a833901
Author: Russ Cox <rsc@golang.org>
Date:   Mon Nov 24 13:24:15 2008 -0800

    Automated g4 rollback of changelist 19916.
    
    *** Reason for rollback ***
    
    broke build
    
    *** Original change description ***
    
    utf8: add InString routines for decoding in strings
    reflect: add InterfaceValue.Get(), remove Empty
    strconv: add Quote, CanBackquote
    fmt:
            * %q go-quoted " string
            * %#q go-quoted ` string if possible, " string otherwise
            * %x hexadecimal string
            * anywhere a string is okay, *[]byte is okay
            * flags # 0 - + space
            * print value inside interface, not interface itself
            * tests
    
    TBR=r
    OCL=19920
    CL=19920

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

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

元コミット内容

このコミットはロールバックであるため、元のコミット(チェンジリスト19916)の内容は以下の通りです。

  • utf8 パッケージ: 文字列内でUTF-8デコードを行うためのInStringルーチンが追加されました。
  • reflect パッケージ: InterfaceValue.Get()メソッドが追加され、Empty型が削除されました。
  • strconv パッケージ: 文字列をクォート(引用符で囲む)するためのQuote関数と、バッククォート( )でクォート可能かを判定するCanBackquote関数が追加されました。
  • fmt パッケージ:
    • %q フォーマット動詞が追加され、Go言語の文字列リテラル形式で文字列をクォートして出力できるようになりました。
    • %#q フォーマット動詞が追加され、可能であればバッククォートで、そうでなければ通常の引用符で文字列をクォートして出力できるようになりました。
    • %x フォーマット動詞が追加され、文字列を16進数形式で出力できるようになりました。
    • 文字列が許容される場所で*[]byte型も許容されるようになりました。
    • #0+- といった新しいフォーマットフラグが追加されました。
    • インターフェース自体ではなく、インターフェース内の値を出力するようになりました。
    • 関連するテストが追加・更新されました。

変更の背景

このコミットは、チェンジリスト19916の自動ロールバックです。ロールバックの理由は、元の変更が「ビルドを壊した」ためと明記されています。これは、Go言語のビルドシステムまたはテストスイートにおいて、チェンジリスト19916が導入された際に何らかのコンパイルエラー、リンクエラー、またはテストの失敗を引き起こしたことを意味します。安定した開発環境を維持するため、問題のある変更は迅速にロールバックされるのが一般的です。

前提知識の解説

  • Go言語のパッケージ: Go言語は、関連する機能の集合を「パッケージ」として整理します。
    • fmt: フォーマットされたI/O(入出力)を実装するパッケージです。PrintfSprintfなどの関数を提供し、様々なデータ型を整形して文字列に出力する機能を持っています。フォーマット動詞(例: %d%s)やフラグ(例: %05d)を使って出力形式を制御します。
    • reflect: 実行時にプログラムの構造を検査・操作するための機能を提供するパッケージです。これにより、変数の型情報や値にアクセスしたり、メソッドを呼び出したりすることが可能になります。
    • strconv: 基本データ型(数値、真偽値など)と文字列との間の変換機能を提供するパッケージです。文字列のクォート(引用符付け)やアンクォート(引用符外し)なども扱います。
    • utf8: UTF-8エンコーディングされたテキストを扱うためのユーティリティ関数を提供するパッケージです。ルーン(Unicodeコードポイント)のデコードやエンコード、バイト列が完全なUTF-8ルーンを表しているかのチェックなどを行います。
  • g4: Google内部で使用されていたバージョン管理システムPerforceのクライアントツールです。Go言語の初期開発はGoogle内部のPerforceシステムで行われていたため、コミットメッセージにg4changelistといった用語が見られます。
  • ロールバック: ソフトウェア開発において、以前のバージョンや状態に戻す操作のことです。問題のある変更が導入された際に、その変更を取り消して安定した状態に戻すために行われます。
  • フォーマット動詞とフラグ: fmtパッケージで使用される特殊な記号で、値の出力形式を指定します。
    • %q: 文字列をGo言語の引用符で囲まれたリテラル形式で出力します。特殊文字はエスケープされます。
    • %x / %X: 数値やバイト列を16進数形式で出力します。%xは小文字、%Xは大文字を使用します。
    • # フラグ: 別の形式(例: 16進数に0xプレフィックスを付ける)を使用したり、%qでバッククォートを使用したりするなど、代替のフォーマットを指定します。
    • 0 フラグ: 数値のゼロパディングを指定します。
    • - フラグ: 左寄せを指定します。
    • + フラグ: 数値の符号(正の場合も+)を常に表示します。
    • (スペース) フラグ: 正の数値の前にスペースを挿入します。
  • インターフェース (Interface): Go言語における抽象型です。メソッドのシグネチャの集合を定義し、そのメソッドを実装する任意の型がそのインターフェースを満たすとされます。

技術的詳細

このコミットはチェンジリスト19916のロールバックであるため、以下の変更は取り消された内容として記述します。

  • fmt パッケージの変更の取り消し:
    • src/lib/fmt/fmt_test.go が削除されました。これは、元の変更で追加されたテストが、このロールバックによって不要になったか、新しいテストフレームワークに移行されたことを示唆しています。実際に、test/fmt_test.goという新しいテストファイルが追加されています。
    • src/lib/fmt/format.go では、Fmt構造体からフォーマットフラグ(minus, plus, sharp, space, zero)のフィールドが削除され、関連するフラグクリアロジックも削除されました。また、文字列のパディングロジックが簡素化され、ゼロパディングや符号表示に関する詳細な制御が取り除かれました。sx(小文字16進数文字列)、sX(大文字16進数文字列)、q(クォート文字列)といった文字列フォーマット用のメソッドが削除されました。
    • src/lib/fmt/print.go では、getField関数が削除され、reflect.InterfaceValueから内部の値を取得するロジックが取り消されました。getString関数における*[]byteの特殊な扱いも削除されました。フォーマット文字列のパースロジックから、#0+- といったフラグの解析部分が削除されました。また、%x%X%qといった新しいフォーマット動詞の処理ロジックも削除されました。getFieldの呼び出しは、より直接的なv.Field(fieldnum)に置き換えられました。
  • reflect パッケージの変更の取り消し:
    • src/lib/reflect/all_test.go からTestInterfaceGetテストが削除されました。
    • src/lib/reflect/cast_amd64.s からAddrToPtrInterfacePtrInterfaceToAddrというアセンブリ関数が削除されました。これらはインターフェース値とアドレス間の変換を扱うものでした。
    • src/lib/reflect/gencast.sh では、Interface型が生成対象から除外される変更が取り消されました。
    • src/lib/reflect/value.go では、Emptyインターフェースの定義がコメントアウトされ、ValueインターフェースのInterface()メソッドの戻り値型がinterface{}からEmptyに変更された部分が元に戻されました。InterfaceValueインターフェースからGet()メソッドが削除され、その実装も削除されました。NewValue関数の引数型もEmptyからinterface{}に戻されました。
  • strconv パッケージの変更の取り消し:
    • src/lib/strconv/Makefile では、quote.oquote.goのコンパイル結果)がビルド対象から除外される変更が取り消され、再び含まれるようになりました。
    • src/lib/strconv/ftoa_test.go から浮動小数点数フォーマットに関する特定のテストケースが削除されました。
    • src/lib/strconv/quote.gosrc/lib/strconv/quote_test.go が完全に削除されました。これは、文字列のクォートとバッククォートに関する機能(QuoteCanBackquote関数)とそのテストが完全に削除されたことを意味します。
  • utf8 パッケージの変更の取り消し:
    • src/lib/utf8.go では、RuneMax定数の値が変更され、DecodeRuneInStringInternalFullRuneInStringDecodeRuneInStringといった文字列を直接扱うUTF-8デコードルーチンが削除されました。
    • src/lib/utf8_test.go では、FullRuneInStringDecodeRuneInStringを使用していたテストが削除され、バイトスライスを扱うFullRuneDecodeRuneに依存する形に戻されました。また、テストヘルパー関数CEscapeが追加されました。

全体として、このロールバックは、Go言語の初期段階におけるfmtreflectstrconvutf8パッケージの設計と実装に関する重要な変更が、ビルドの安定性を損なったために一時的に取り消されたことを示しています。特に、文字列の高度なフォーマット機能、リフレクションにおけるインターフェース値の扱い、そしてUTF-8文字列処理の最適化が、この時点ではまだ安定していなかったことが伺えます。

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

このコミットはロールバックであるため、以下の箇所が元の変更によって追加され、このコミットによって削除されたコアなコード変更箇所となります。

  • src/lib/fmt/format.go:
    • Fmt構造体からフォーマットフラグ(minus, plus, sharp, space, zero)の定義と、それらをクリアするclearflags()内のロジックが削除されました。
    • padメソッド内のパディング文字(padchar)の選択ロジック(f.zeroによる'0'パディング)が削除され、常にスペースでパディングするようになりました。
    • integerメソッド内のゼロパディングと符号表示に関する詳細なロジック(preczeroの相互作用、f.plusf.spaceによる符号の挿入)が削除されました。
    • sx, sX, qといった文字列フォーマット用のメソッドが完全に削除されました。
  • src/lib/fmt/print.go:
    • getField関数が削除されました。この関数はreflect.InterfaceValueから内部の値を取り出す役割を持っていました。
    • getString関数内の*[]byte型を文字列として扱う特殊なケースが削除されました。
    • doprintf関数内のフォーマット文字列パースロジックから、#, 0, +, -, といったフラグの解析部分が削除されました。
    • doprintf関数内のcase 'x', case 'X', case 'q'といった新しいフォーマット動詞の処理ブロックが削除されました。
  • src/lib/reflect/value.go:
    • export type Empty interface {} の定義が削除されました。
    • InterfaceValueインターフェースからGet()メソッドの定義が削除され、InterfaceValueStruct構造体からその実装も削除されました。
    • NewValue関数のシグネチャがexport func NewValue(e Empty) Valueからexport func NewValue(e interface {}) Valueに戻されました。
  • src/lib/strconv/quote.go: ファイル全体が削除されました。これにより、Quote関数とCanBackquote関数が完全に失われました。
  • src/lib/utf8.go:
    • DecodeRuneInStringInternal, FullRuneInString, DecodeRuneInStringといった、文字列を直接引数に取るUTF-8デコード関連の関数が削除されました。

コアとなるコードの解説

このロールバックによって削除された(元のコミットで追加された)コアなコードは、Go言語の初期の設計思想と実装の進化を反映しています。

  • fmt パッケージの変更: 元のコミットでは、fmtパッケージにC言語のprintfライクな機能(特にフラグによる詳細な制御)と、Go言語特有の文字列クォート(%q, %#q)やバイト列の16進数表示(%x, %X)が導入されようとしていました。これらの機能は、より柔軟で表現力豊かなフォーマットを可能にするものでしたが、ビルドを壊したため、この時点では安定した実装が困難であったか、既存のコードベースとの互換性問題を引き起こした可能性があります。特に、*[]byteを文字列として扱えるようにする変更は、型システムにおける暗黙の変換や、バイト列と文字列の厳密な区別というGoの原則に反する可能性があり、問題の原因となったかもしれません。
  • reflect パッケージの変更: InterfaceValue.Get()の追加は、リフレクションを通じてインターフェースの内部に格納された具体的な値に直接アクセスする手段を提供しようとしたものです。Emptyインターフェースの導入は、おそらくinterface{}の別名または特定の用途に特化したインターフェースとして試みられたものですが、これもリフレクションの設計に複雑さをもたらしたか、意図しない副作用を引き起こした可能性があります。これらの変更のロールバックは、リフレクションのAPI設計がまだ流動的であり、安定したインターフェースを提供するための試行錯誤が行われていたことを示しています。
  • strconv パッケージの変更: QuoteCanBackquote関数の削除は、文字列のクォート処理がstrconvパッケージから切り離されたことを意味します。これは、クォート処理がfmtパッケージの内部機能として統合されるか、あるいはより汎用的なユーティリティとして再設計される必要があったことを示唆しています。特に、バッククォートの扱いはGo言語の文字列リテラルの特殊な形式であり、その適切な処理は複雑さを伴います。
  • utf8 パッケージの変更: InStringルーチンの削除は、UTF-8デコードがバイトスライスに対して行われるのが基本であり、文字列を直接引数に取るデコード関数は、パフォーマンスやメモリ割り当ての観点から最適ではなかったか、あるいは設計上の問題があったことを示唆しています。Go言語では文字列は不変のバイトスライスとして扱われるため、文字列を直接操作するよりもバイトスライスとして扱う方が効率的な場合があります。

このロールバックは、Go言語の初期開発において、機能追加と安定性のバランスを取ることの難しさ、そしてAPI設計における試行錯誤の過程を明確に示しています。ビルドの破損という具体的な問題が、これらの変更を一時的に撤回する決定的な要因となりました。

関連リンク

参考にした情報源リンク

  • コミットメッセージ (commit 85fea81d70d0af531944cc6ceacf955b4a833901)
  • GitHub上のコミット差分 (https://github.com/golang/go/commit/85fea81d70d0af531944cc6ceacf955b4a833901)
  • Go言語の公式ドキュメント(fmt, reflect, strconv, utf8パッケージに関する一般的な情報)
  • Go言語の歴史と設計に関する一般的な知識