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

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

misc/dashboard/builder/main.go は、Goプロジェクトのダッシュボードシステムの一部であり、ビルドの状態やコミットログを収集・処理する役割を担っています。具体的には、Mercurial (hg) リポジトリからコミットログをXML形式で取得し、それをGoの構造体にアンマーシャル(unmarshal)して、ダッシュボードに表示するためのデータを準備しています。このファイルは、リポジトリの変更をポーリングし、新しいコミット情報を解析してシステムに反映させるための重要なコンポーネントです。

コミット

commit c1b4be6a4dbbdce9c69d028a8652731652d7babc
Author: Russ Cox <rsc@golang.org>
Date:   Mon Jan 23 11:50:39 2012 -0500

    dashboard: fix -commit for new xml package
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/5571046

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

https://github.com/golang/go/commit/c1b4be6a4dbbdce9c69d028a8652731652d7babc

元コミット内容

dashboard: fix -commit for new xml package

変更の背景

このコミットは、Go言語の標準ライブラリである encoding/xml パッケージの変更に対応するために行われました。以前の encoding/xml パッケージでは、XML要素名とGoの構造体フィールド名のマッピングにおいて、大文字・小文字を区別しない、あるいはより柔軟なマッチングが行われていた可能性があります。しかし、新しい encoding/xml パッケージでは、このマッチングルールが厳格化され、XML要素名とGoの構造体フィールド名(または構造体タグで指定された名前)が正確に一致する必要が生じました。

misc/dashboard/builder/main.go では、Mercurialのログ出力をXMLとして解析するために、xmlLogTemplate というXMLテンプレートと、xml.Unmarshal 関数を使用していました。新しい encoding/xml パッケージの導入により、既存のXMLテンプレートで定義されていた小文字の要素名(例: <log>, <hash>) が、Goの構造体フィールド名と正しくマッピングされなくなりました。また、xml.Unmarshal に渡すルート要素名も同様に、構造体と一致するように変更する必要がありました。

この変更は、Go言語の進化に伴うライブラリの改善の一環であり、より堅牢で予測可能なXML処理を実現するためのものでした。そのため、既存のコードベースが新しいライブラリの挙動に適合するように修正する必要がありました。

前提知識の解説

Go言語の encoding/xml パッケージ

encoding/xml パッケージは、Go言語でXMLデータをエンコード(Goの構造体からXMLへ)およびデコード(XMLからGoの構造体へ)するための標準ライブラリです。このパッケージの主要な機能の一つに xml.Unmarshal 関数があります。

xml.Unmarshal 関数

xml.Unmarshal 関数は、XMLデータをGoの構造体にデコードするために使用されます。この関数は、XML要素名とGoの構造体フィールド名をマッピングすることで機能します。デフォルトでは、xml.Unmarshal はXML要素名をGoの構造体フィールド名と照合しようとします。フィールド名がエクスポートされている(大文字で始まる)場合、その名前が使用されます。

構造体タグ (Struct Tags)

Goの構造体では、フィールドに「構造体タグ」と呼ばれるメタデータを付与することができます。encoding/xml パッケージでは、xml:"element_name" の形式でタグを指定することで、XML要素名とGoの構造体フィールド名のマッピングを明示的に制御できます。例えば、Field string xml:"my_element"のように記述すると、XML内の<my_element>要素がGoの構造体のField` フィールドにマッピングされます。

XML要素名とGo構造体フィールド名のマッピング

xml.Unmarshal がXMLデータをGoの構造体にデコードする際、XML要素名とGoの構造体フィールド名のマッピングは非常に重要です。このマッピングのルールは、encoding/xml パッケージのバージョンによって異なる場合があります。特に、大文字・小文字の区別や、構造体タグの有無がマッピングの成否に影響を与えます。

このコミットの背景にあるのは、encoding/xml パッケージが、XML要素名とGo構造体フィールド名のマッチングにおいて、より厳密な大文字・小文字の区別を導入した、あるいはデフォルトのマッチング戦略を変更したという点です。これにより、以前はマッチしていた小文字のXML要素名が、Goの構造体フィールド名(通常は大文字で始まる)とマッチしなくなり、明示的な修正が必要となりました。

技術的詳細

このコミットの技術的な核心は、Goの encoding/xml パッケージにおけるXML要素名とGo構造体フィールド名のマッピングルールの変更にあります。具体的には、以下の2つの変更が適用されています。

  1. XMLテンプレート内の要素名の大文字化: xmlLogTemplate 定数内で定義されているXML要素名が、すべて小文字から大文字に修正されました。

    • <log> から <Log>
    • <hash> から <Hash>
    • <parent> から <Parent>
    • <author> から <Author>
    • <date> から <Date>
    • <desc> から <Desc>

    これは、Goの構造体フィールド名が慣習的に大文字で始まる(エクスポートされる)ため、新しい encoding/xml パッケージがXML要素名とGo構造体フィールド名をより厳密に照合するようになったことを示唆しています。例えば、Goの構造体に type HgLog struct { Hash string } のようなフィールドがある場合、以前の encoding/xml パッケージではXMLの <hash> 要素がこの Hash フィールドにマッピングされていたかもしれませんが、新しいパッケージでは <Hash> でなければ正しくマッピングされなくなったと考えられます。

  2. xml.Unmarshal のルート要素名の大文字化: xml.Unmarshal 関数に渡されるXML文字列のルート要素名が、<top> から <Top> に変更されました。 err = xml.Unmarshal(strings.NewReader("<top>"+data+"</top>"), &logStruct)err = xml.Unmarshal(strings.NewReader("<Top>"+data+"</Top>"), &logStruct) に変更されています。

    これは、logStruct の定義が struct { Log []HgLog } であり、この Log フィールドがXMLのルート要素に対応すると考えられるためです。新しい encoding/xml パッケージでは、ルート要素名もGoの構造体フィールド名(または構造体タグで指定された名前)と正確に一致する必要があるため、Top に変更されました。

これらの変更は、encoding/xml パッケージがXMLのパースにおいて、より厳密なマッチングセマンティクスを採用した結果です。これにより、開発者はXML構造とGo構造体のマッピングをより明示的に、かつ正確に定義する必要が生じました。これは、XML処理の堅牢性を高め、予期せぬマッピングエラーを防ぐための改善と見なすことができます。

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

変更は misc/dashboard/builder/main.go ファイルに集中しています。

--- a/misc/dashboard/builder/main.go
+++ b/misc/dashboard/builder/main.go
@@ -533,13 +533,13 @@ var logByHash = map[string]*HgLog{}
 // xmlLogTemplate is a template to pass to Mercurial to make
 // hg log print the log in valid XML for parsing with xml.Unmarshal.
 const xmlLogTemplate = `
-	<log>
-	<hash>{node|escape}</hash>
-	<parent>{parent|escape}</parent>
-	<author>{author|escape}</author>
-	<date>{date|rfc3339date}</date>
-	<desc>{desc|escape}</desc>
-	</log>
+	<Log>
+	<Hash>{node|escape}</Hash>
+	<Parent>{parent|escape}</Parent>
+	<Author>{author|escape}</Author>
+	<Date>{date|rfc3339date}</Date>
+	<Desc>{desc|escape}</Desc>
+	</Log>
 `
 
 // commitPoll pulls any new revisions from the hg server
@@ -587,7 +587,7 @@ func commitPoll(key, pkg string) {\
 	var logStruct struct {\
 		Log []HgLog\
 	}\
-\terr = xml.Unmarshal(strings.NewReader("<top>"+data+"</top>"), &logStruct)\
+\terr = xml.Unmarshal(strings.NewReader("<Top>"+data+"</Top>"), &logStruct)\
 \tif err != nil {\
 \t\tlog.Printf("unmarshal hg log: %v", err)\
 \t\treturn\

コアとなるコードの解説

このコミットでは、主に2つのコードブロックが変更されています。

  1. xmlLogTemplate 定数の変更: この定数は、Mercurialのログ出力をXML形式で整形するためのテンプレート文字列を定義しています。変更前は、XML要素名がすべて小文字で定義されていました(例: <log>, <hash>)。変更後は、これらの要素名がすべて大文字の先頭文字を持つように修正されました(例: <Log>, <Hash>)。 これは、Goの encoding/xml パッケージが、XML要素名とGoの構造体フィールド名(または構造体タグで指定された名前)をマッピングする際に、より厳密な大文字・小文字の区別を要求するようになったためです。Goの構造体フィールドは通常、エクスポートされるために大文字で始まるため、XML要素名もそれに合わせて大文字で始まるように変更することで、xml.Unmarshal が正しくマッピングできるようになります。

  2. xml.Unmarshal 関数の呼び出し箇所の変更: commitPoll 関数内で、Mercurialから取得したXMLデータを xml.Unmarshal でGoの構造体にデコードする際に、XML文字列のルート要素名が変更されました。 変更前は、"<top>" という小文字のルート要素が使用されていました。変更後は、"<Top>" という大文字のルート要素に変更されています。 これは、logStruct という匿名構造体が Log []HgLog というフィールドを持っているため、xml.Unmarshal がこの Log フィールドをXMLのルート要素として認識するように、ルート要素名も大文字の Top に合わせる必要があったためです。この変更も、encoding/xml パッケージの厳格化されたマッピングルールに対応するためのものです。

これらの変更により、misc/dashboard/builder/main.go は、新しい encoding/xml パッケージの挙動に適合し、Mercurialのログデータを正しくXMLとして解析し、Goの構造体にデコードできるようになりました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • encoding/xml パッケージの変更履歴に関する情報 (具体的なバージョンアップによる変更点については、当時のGoのリリースノートやコミット履歴を詳細に調査する必要がありますが、一般的なGoのXML処理の知識に基づいています。)
  • GitHubのコミット履歴: https://github.com/golang/go/commit/c1b4be6a4dbbdce9c69d028a8652731652d7babc
  • Go CL 5571046: https://golang.org/cl/5571046 (このコミットのChange-ID)
  • Go言語のXML処理に関する一般的な情報源