[インデックス 15709] ファイルの概要
このコミットは、Go言語の標準ライブラリ encoding/xml
パッケージにおける、XMLマーシャリング(Goのデータ構造をXMLに変換する処理)の改善に関するものです。具体的には、Goの構造体内に非構造体型(例:int
、string
などの基本型)が埋め込まれている場合に、それらを正しくXMLとして処理できるようにする変更が加えられました。
コミット
commit aa81eb5901abc545bc8ff14833f52c3e798f0b90
Author: Russ Cox <rsc@golang.org>
Date: Mon Mar 11 23:58:20 2013 -0400
encoding/xml: allow embedded non-structs
The old code just assumed that the only thing
you can embed is a struct. Not true.
Fixes #3803.
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/7743043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/aa81eb5901abc545bc8ff14833f52c3e798f0b90
元コミット内容
このコミットの元の内容は、encoding/xml
パッケージが、Goの構造体における埋め込みフィールドの処理方法を修正することです。以前のコードでは、埋め込みフィールドは常に構造体であると誤って仮定していました。しかし、Goの言語仕様では、構造体だけでなく、基本型やインターフェースなどの非構造体型も埋め込むことが可能です。このコミットは、この誤った仮定を修正し、非構造体型の埋め込みもXMLマーシャリングで正しく扱えるようにします。これにより、関連するバグ(Issue #3803)が修正されます。
変更の背景
Go言語の構造体埋め込み(embedding)は、コードの再利用性を高める強力な機能です。ある型を別の構造体に埋め込むことで、埋め込まれた型のメソッドやフィールドを、埋め込み先の構造体が直接持っているかのようにアクセスできます。これは、継承に似た振る舞いを実現しますが、Goのコンポジション(合成)の原則に基づいています。
encoding/xml
パッケージは、Goのデータ構造とXMLの間で変換を行うための標準ライブラリです。XMLへのマーシャリング(Goの構造体をXMLに変換)やXMLからのアンマーシャリング(XMLをGoの構造体に変換)を担います。
このコミットが行われる以前は、encoding/xml
パッケージの内部ロジック、特に型情報を解析する部分(typeinfo.go
)において、埋め込みフィールドが常に構造体であるという誤った前提がありました。このため、例えば以下のようなコードは、XMLマーシャリング時に期待通りに動作しませんでした。
type MyInt int
type EmbedInt struct {
MyInt // int型を埋め込み
}
// EmbedInt{MyInt: 42} をXMLにマーシャリングしようとすると問題が発生していた
この問題は、Goの言語仕様と encoding/xml
パッケージの実装との間の不一致によって引き起こされていました。ユーザーが非構造体型を埋め込んだ構造体をXMLにマーシャリングしようとすると、予期せぬ結果になったり、エラーが発生したりする可能性がありました。この不具合はIssue #3803として報告されており、このコミットはその修正を目的としています。
前提知識の解説
Go言語の構造体埋め込み (Struct Embedding)
Go言語の構造体埋め込みは、ある型を別の構造体の中にフィールド名なしで宣言することで実現されます。これにより、埋め込まれた型のフィールドやメソッドが、埋め込み先の構造体のトップレベルのフィールドやメソッドであるかのように昇格(promote)されます。
例:
type Base struct {
ID int
Name string
}
type User struct {
Base // Base型を埋め込み
Email string
}
func main() {
u := User{Base: Base{ID: 1, Name: "Alice"}, Email: "alice@example.com"}
fmt.Println(u.ID) // Base.ID にアクセス
fmt.Println(u.Name) // Base.Name にアクセス
}
この機能は、コードの再利用や、インターフェースの実装を簡潔にするためによく使用されます。重要なのは、埋め込み可能なのは構造体だけでなく、任意の型(基本型、インターフェース、ポインタなど)であるという点です。
Goの reflect
パッケージ
reflect
パッケージは、Goのプログラムが実行時に自身の構造を検査(introspection)し、変更(manipulation)することを可能にする機能を提供します。これにより、型情報(reflect.Type
)や値情報(reflect.Value
)を動的に取得・操作できます。
encoding/xml
のような汎用的なマーシャリングライブラリは、ユーザーが定義した任意のGoの型を処理する必要があるため、reflect
パッケージを多用します。特に、構造体のフィールドを走査し、その型やタグ情報を読み取るために不可欠です。
reflect.Type
: Goの型の静的な情報(名前、種類、メソッドなど)を表します。reflect.Value
: Goの値の動的な情報(実際の値、変更可能性など)を表します。Type.Kind()
:reflect.Type
のメソッドで、その型がどのような種類(reflect.Struct
,reflect.Int
,reflect.String
など)であるかを返します。
XMLマーシャリングの概念
XMLマーシャリングとは、Goのプログラム内で使用されるデータ構造(通常は構造体)を、XML形式の文字列やバイト列に変換するプロセスを指します。このプロセスでは、Goの構造体のフィールド名がXML要素名や属性名にマッピングされ、フィールドの値がXML要素のテキストコンテンツや属性値になります。
encoding/xml
パッケージは、構造体のフィールドタグ(例: xml:"name,attr"
)を使用して、マーシャリング時のXML要素名や属性の振る舞いを制御します。
技術的詳細
このコミットの技術的な核心は、encoding/xml
パッケージがGoの型情報を解析する getTypeInfo
関数(src/pkg/encoding/xml/typeinfo.go
内)のロジック修正にあります。
以前の getTypeInfo
関数は、構造体のフィールドを走査する際に、埋め込みフィールド(f.Anonymous
が true
のフィールド)を見つけると、その埋め込みフィールドの型が reflect.Struct
であるかどうかを厳密にチェックしていました。
変更前のロジックの抜粋(擬似コード):
// 埋め込みフィールドの場合
if f.Anonymous {
t := f.Type // 埋め込みフィールドの型
if t.Kind() == reflect.Ptr {
t = t.Elem() // ポインタであれば参照解除
}
// ここが問題の箇所: 埋め込みフィールドが構造体でなければ、このフィールドをスキップする
if t.Kind() != reflect.Struct {
continue // 次のフィールドへ
}
// 埋め込みフィールドが構造体であれば、その内部フィールドを再帰的に処理する
innerTypeInfo, err := getTypeInfo(t)
// ... innerTypeInfo のフィールドを現在の型情報に追加 ...
continue // 埋め込み構造体の処理後、次のフィールドへ
}
// 通常のフィールド処理ロジック(埋め込み非構造体はここに到達しない)
このロジックでは、MyInt
のような非構造体型が埋め込まれている場合、t.Kind() != reflect.Struct
の条件が true
となり、continue
ステートメントによってその埋め込みフィールドは完全にスキップされていました。結果として、encoding/xml
は非構造体型の埋め込みフィールドを認識せず、XML出力に含めることができませんでした。
変更後のロジックの抜粋(擬似コード):
// 埋め込みフィールドの場合
if f.Anonymous {
t := f.Type // 埋め込みフィールドの型
if t.Kind() == reflect.Ptr {
t = t.Elem() // ポインタであれば参照解除
}
// 埋め込みフィールドが構造体であれば、その内部フィールドを再帰的に処理する
if t.Kind() == reflect.Struct { // 条件が反転
innerTypeInfo, err := getTypeInfo(t)
// ... innerTypeInfo のフィールドを現在の型情報に追加 ...
continue // 埋め込み構造体の処理後、次のフィールドへ
}
// ここが変更点: 埋め込みフィールドが構造体でなければ、
// スキップせずに通常のフィールド処理ロジックにフォールスルーさせる
}
// 通常のフィールド処理ロジック(埋め込み非構造体はここに到達するようになった)
この修正により、埋め込みフィールドが構造体である場合にのみ、その内部フィールドを再帰的に処理し、それ以外(非構造体型)の場合は、その埋め込みフィールドを通常のフィールドとして扱うための後続のロジックに処理を委ねるようになりました。これにより、encoding/xml
は MyInt
のような埋め込み非構造体型も正しくXML要素としてマーシャリングできるようになります。
marshal_test.go
に追加されたテストケースは、この新しい振る舞いを検証するためのものです。EmbedInt
構造体に MyInt
型(int
のエイリアス)を埋め込み、その構造体が期待通りのXML出力にマーシャリングされることを確認しています。
コアとなるコードの変更箇所
このコミットで変更された主要なファイルは以下の2つです。
-
src/pkg/encoding/xml/marshal_test.go
- 新しいテストケース
EmbedInt
とMyInt
が追加されました。 marshalTests
スライスに、EmbedInt
型の値をマーシャリングするテストエントリが追加されました。これは、非構造体型の埋め込みが正しく処理されることを検証します。
- 新しいテストケース
-
src/pkg/encoding/xml/typeinfo.go
getTypeInfo
関数内の、埋め込みフィールドを処理するロジックが変更されました。- 具体的には、埋め込みフィールドの型が構造体であるかどうかをチェックする条件
if t.Kind() != reflect.Struct
がif t.Kind() == reflect.Struct
に変更され、それに伴いcontinue
ステートメントの位置が調整されました。
コアとなるコードの解説
src/pkg/encoding/xml/marshal_test.go
の変更
// 新しい型定義: int型をエイリアスしたMyIntと、MyIntを埋め込んだEmbedInt
type MyInt int
type EmbedInt struct {
MyInt
}
// marshalTests スライスに新しいテストケースを追加
// EmbedInt{MyInt: 42} が <EmbedInt><MyInt>42</MyInt></EmbedInt> にマーシャリングされることを期待
{
ExpectXML: `<EmbedInt><MyInt>42</MyInt></EmbedInt>`,
Value: &EmbedInt{
MyInt: 42,
},
},
このテストケースは、int
型をエイリアスした MyInt
を EmbedInt
構造体に埋め込み、その EmbedInt
のインスタンスをXMLにマーシャリングした際に、期待されるXML出力が得られることを確認します。これにより、encoding/xml
が非構造体型の埋め込みを正しく処理できるようになったことが検証されます。
src/pkg/encoding/xml/typeinfo.go
の変更
--- a/src/pkg/encoding/xml/typeinfo.go
+++ b/src/pkg/encoding/xml/typeinfo.go
@@ -70,20 +70,19 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
- if t.Kind() != reflect.Struct { // 変更前: 構造体でなければスキップ
- continue
- }
- inner, err := getTypeInfo(t)
- if err != nil {
- return nil, err
- }
- for _, finfo := range inner.fields {
- finfo.idx = append([]int{i}, finfo.idx...)
- if err := addFieldInfo(typ, tinfo, &finfo); err != nil {
- return nil, err
- }
- }
- continue
+ if t.Kind() == reflect.Struct { // 変更後: 構造体であれば処理
+ inner, err := getTypeInfo(t)
+ if err != nil {
+ return nil, err
+ }
+ for _, finfo := range inner.fields {
+ finfo.idx = append([]int{i}, finfo.idx...)
+ if err := addFieldInfo(typ, tinfo, &finfo); err != nil {
+ return nil, err
+ }
+ }
+ continue // 構造体埋め込みの処理後、次のフィールドへ
+ }
}
finfo, err := structFieldInfo(typ, &f)
このdiffは、getTypeInfo
関数内の埋め込みフィールド処理ロジックの核心を示しています。
-
変更前:
if t.Kind() != reflect.Struct { continue }
- これは、「もし埋め込みフィールドの型が構造体でなければ、この埋め込みフィールドの処理をスキップし、次のフィールドへ進む」という意味でした。このため、
MyInt
のような非構造体型の埋め込みは無視されていました。
- これは、「もし埋め込みフィールドの型が構造体でなければ、この埋め込みフィールドの処理をスキップし、次のフィールドへ進む」という意味でした。このため、
-
変更後:
if t.Kind() == reflect.Struct { ... continue }
- これは、「もし埋め込みフィールドの型が構造体であれば、その内部フィールドを再帰的に処理し、その後次のフィールドへ進む」という意味になります。
- 重要なのは、
if
ブロックの後にcontinue
があるため、埋め込みフィールドが構造体でない場合(例:MyInt
)、そのフィールドはif t.Kind() == reflect.Struct
の条件を満たさず、if
ブロック内のコードは実行されません。そして、continue
も実行されないため、処理はif f.Anonymous
ブロックの後の通常のフィールド処理ロジック(finfo, err := structFieldInfo(typ, &f)
から始まる部分)にフォールスルーします。 - このフォールスルーにより、非構造体型の埋め込みフィールドも、通常のフィールドと同様に
encoding/xml
によって適切に処理されるようになりました。
関連リンク
- Go言語の構造体埋め込みに関する公式ドキュメントやチュートリアル
encoding/xml
パッケージの公式ドキュメント- Goの
reflect
パッケージの公式ドキュメント
参考にした情報源リンク
- Go Issue #3803: encoding/xml: allow embedded non-structs
- Go Change-Id: 7743043 (Gerrit)
- GoDoc: encoding/xml
- GoDoc: reflect
- A Tour of Go: Embedded fields
- Effective Go: Embedding
[インデックス 15709] ファイルの概要
このコミットは、Go言語の標準ライブラリ encoding/xml
パッケージにおける、XMLマーシャリング(Goのデータ構造をXMLに変換する処理)の改善に関するものです。具体的には、Goの構造体内に非構造体型(例:int
、string
などの基本型)が埋め込まれている場合に、それらを正しくXMLとして処理できるようにする変更が加えられました。
コミット
commit aa81eb5901abc545bc8ff14833f52c3e798f0b90
Author: Russ Cox <rsc@golang.org>
Date: Mon Mar 11 23:58:20 2013 -0400
encoding/xml: allow embedded non-structs
The old code just assumed that the only thing
you can embed is a struct. Not true.
Fixes #3803.
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/7743043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/aa81eb5901abc545bc8ff14833f52c3e798f0b90
元コミット内容
このコミットの元の内容は、encoding/xml
パッケージが、Goの構造体における埋め込みフィールドの処理方法を修正することです。以前のコードでは、埋め込みフィールドは常に構造体であると誤って仮定していました。しかし、Goの言語仕様では、構造体だけでなく、基本型やインターフェースなどの非構造体型も埋め込むことが可能です。このコミットは、この誤った仮定を修正し、非構造体型の埋め込みもXMLマーシャリングで正しく扱えるようにします。これにより、関連するバグ(Issue #3803)が修正されます。
変更の背景
Go言語の構造体埋め込み(embedding)は、コードの再利用性を高める強力な機能です。ある型を別の構造体に埋め込むことで、埋め込まれた型のメソッドやフィールドを、埋め込み先の構造体が直接持っているかのようにアクセスできます。これは、継承に似た振る舞いを実現しますが、Goのコンポジション(合成)の原則に基づいています。
encoding/xml
パッケージは、Goのデータ構造とXMLの間で変換を行うための標準ライブラリです。XMLへのマーシャリング(Goの構造体をXMLに変換)やXMLからのアンマーシャリング(XMLをGoの構造体に変換)を担います。
このコミットが行われる以前は、encoding/xml
パッケージの内部ロジック、特に型情報を解析する部分(typeinfo.go
)において、埋め込みフィールドが常に構造体であるという誤った前提がありました。このため、例えば以下のようなコードは、XMLマーシャリング時に期待通りに動作しませんでした。
type MyInt int
type EmbedInt struct {
MyInt // int型を埋め込み
}
// EmbedInt{MyInt: 42} をXMLにマーシャリングしようとすると問題が発生していた
この問題は、Goの言語仕様と encoding/xml
パッケージの実装との間の不一致によって引き起こされていました。ユーザーが非構造体型を埋め込んだ構造体をXMLにマーシャリングしようとすると、予期せぬ結果になったり、エラーが発生したりする可能性がありました。この不具合はIssue #3803として報告されており、このコミットはその修正を目的としています。
前提知識の解説
Go言語の構造体埋め込み (Struct Embedding)
Go言語の構造体埋め込みは、ある型を別の構造体の中にフィールド名なしで宣言することで実現されます。これにより、埋め込まれた型のフィールドやメソッドが、埋め込み先の構造体のトップレベルのフィールドやメソッドであるかのように昇格(promote)されます。
例:
type Base struct {
ID int
Name string
}
type User struct {
Base // Base型を埋め込み
Email string
}
func main() {
u := User{Base: Base{ID: 1, Name: "Alice"}, Email: "alice@example.com"}
fmt.Println(u.ID) // Base.ID にアクセス
fmt.Println(u.Name) // Base.Name にアクセス
}
この機能は、コードの再利用や、インターフェースの実装を簡潔にするためによく使用されます。重要なのは、埋め込み可能なのは構造体だけでなく、任意の型(基本型、インターフェース、ポインタなど)であるという点です。
Goの reflect
パッケージ
reflect
パッケージは、Goのプログラムが実行時に自身の構造を検査(introspection)し、変更(manipulation)することを可能にする機能を提供します。これにより、型情報(reflect.Type
)や値情報(reflect.Value
)を動的に取得・操作できます。
encoding/xml
のような汎用的なマーシャリングライブラリは、ユーザーが定義した任意のGoの型を処理する必要があるため、reflect
パッケージを多用します。特に、構造体のフィールドを走査し、その型やタグ情報を読み取るために不可欠です。
reflect.Type
: Goの型の静的な情報(名前、種類、メソッドなど)を表します。reflect.Value
: Goの値の動的な情報(実際の値、変更可能性など)を表します。Type.Kind()
:reflect.Type
のメソッドで、その型がどのような種類(reflect.Struct
,reflect.Int
,reflect.String
など)であるかを返します。
XMLマーシャリングの概念
XMLマーシャリングとは、Goのプログラム内で使用されるデータ構造(通常は構造体)を、XML形式の文字列やバイト列に変換するプロセスを指します。このプロセスでは、Goの構造体のフィールド名がXML要素名や属性名にマッピングされ、フィールドの値がXML要素のテキストコンテンツや属性値になります。
encoding/xml
パッケージは、構造体のフィールドタグ(例: xml:"name,attr"
)を使用して、マーシャリング時のXML要素名や属性の振る舞いを制御します。
技術的詳細
このコミットの技術的な核心は、encoding/xml
パッケージがGoの型情報を解析する getTypeInfo
関数(src/pkg/encoding/xml/typeinfo.go
内)のロジック修正にあります。
以前の getTypeInfo
関数は、構造体のフィールドを走査する際に、埋め込みフィールド(f.Anonymous
が true
のフィールド)を見つけると、その埋め込みフィールドの型が reflect.Struct
であるかどうかを厳密にチェックしていました。
変更前のロジックの抜粋(擬似コード):
// 埋め込みフィールドの場合
if f.Anonymous {
t := f.Type // 埋め込みフィールドの型
if t.Kind() == reflect.Ptr {
t = t.Elem() // ポインタであれば参照解除
}
// ここが問題の箇所: 埋め込みフィールドが構造体でなければ、このフィールドをスキップする
if t.Kind() != reflect.Struct {
continue // 次のフィールドへ
}
// 埋め込みフィールドが構造体であれば、その内部フィールドを再帰的に処理する
innerTypeInfo, err := getTypeInfo(t)
// ... innerTypeInfo のフィールドを現在の型情報に追加 ...
continue // 埋め込み構造体の処理後、次のフィールドへ
}
// 通常のフィールド処理ロジック(埋め込み非構造体はここに到達しない)
このロジックでは、MyInt
のような非構造体型が埋め込まれている場合、t.Kind() != reflect.Struct
の条件が true
となり、continue
ステートメントによってその埋め込みフィールドは完全にスキップされていました。結果として、encoding/xml
は非構造体型の埋め込みフィールドを認識せず、XML出力に含めることができませんでした。
変更後のロジックの抜粋(擬似コード):
// 埋め込みフィールドの場合
if f.Anonymous {
t := f.Type // 埋め込みフィールドの型
if t.Kind() == reflect.Ptr {
t = t.Elem() // ポインタであれば参照解除
}
// 埋め込みフィールドが構造体であれば、その内部フィールドを再帰的に処理する
if t.Kind() == reflect.Struct { // 条件が反転
innerTypeInfo, err := getTypeInfo(t)
if err != nil {
return nil, err
}
// ... innerTypeInfo のフィールドを現在の型情報に追加 ...
continue // 埋め込み構造体の処理後、次のフィールドへ
}
// ここが変更点: 埋め込みフィールドが構造体でなければ、
// スキップせずに通常のフィールド処理ロジックにフォールスルーさせる
}
// 通常のフィールド処理ロジック(埋め込み非構造体はここに到達するようになった)
この修正により、埋め込みフィールドが構造体である場合にのみ、その内部フィールドを再帰的に処理し、それ以外(非構造体型)の場合は、その埋め込みフィールドを通常のフィールドとして扱うための後続のロジックに処理を委ねるようになりました。これにより、encoding/xml
は MyInt
のような埋め込み非構造体型も正しくXML要素としてマーシャリングできるようになります。
marshal_test.go
に追加されたテストケースは、この新しい振る舞いを検証するためのものです。EmbedInt
構造体に MyInt
型(int
のエイリアス)を埋め込み、その構造体が期待通りのXML出力にマーシャリングされることを確認しています。
コアとなるコードの変更箇所
このコミットで変更された主要なファイルは以下の2つです。
-
src/pkg/encoding/xml/marshal_test.go
- 新しいテストケース
EmbedInt
とMyInt
が追加されました。 marshalTests
スライスに、EmbedInt
型の値をマーシャリングするテストエントリが追加されました。これは、非構造体型の埋め込みが正しく処理されることを検証します。
- 新しいテストケース
-
src/pkg/encoding/xml/typeinfo.go
getTypeInfo
関数内の、埋め込みフィールドを処理するロジックが変更されました。- 具体的には、埋め込みフィールドの型が構造体であるかどうかをチェックする条件
if t.Kind() != reflect.Struct
がif t.Kind() == reflect.Struct
に変更され、それに伴いcontinue
ステートメントの位置が調整されました。
コアとなるコードの解説
src/pkg/encoding/xml/marshal_test.go
の変更
// 新しい型定義: int型をエイリアスしたMyIntと、MyIntを埋め込んだEmbedInt
type MyInt int
type EmbedInt struct {
MyInt
}
// marshalTests スライスに新しいテストケースを追加
// EmbedInt{MyInt: 42} が <EmbedInt><MyInt>42</MyInt></EmbedInt> にマーシャリングされることを期待
{
ExpectXML: `<EmbedInt><MyInt>42</MyInt></EmbedInt>`,
Value: &EmbedInt{
MyInt: 42,
},
},
このテストケースは、int
型をエイリアスした MyInt
を EmbedInt
構造体に埋め込み、その EmbedInt
のインスタンスをXMLにマーシャリングした際に、期待されるXML出力が得られることを確認します。これにより、encoding/xml
が非構造体型の埋め込みを正しく処理できるようになったことが検証されます。
src/pkg/encoding/xml/typeinfo.go
の変更
--- a/src/pkg/encoding/xml/typeinfo.go
+++ b/src/pkg/encoding/xml/typeinfo.go
@@ -70,20 +70,19 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
- if t.Kind() != reflect.Struct { // 変更前: 構造体でなければスキップ
- continue
- }
- inner, err := getTypeInfo(t)
- if err != nil {
- return nil, err
- }
- for _, finfo := range inner.fields {
- finfo.idx = append([]int{i}, finfo.idx...)
- if err := addFieldInfo(typ, tinfo, &finfo); err != nil {
- return nil, err
- }
- }
- continue
+ if t.Kind() == reflect.Struct { // 変更後: 構造体であれば処理
+ inner, err := getTypeInfo(t)
+ if err != nil {
+ return nil, err
+ }
+ for _, finfo := range inner.fields {
+ finfo.idx = append([]int{i}, finfo.idx...)
+ if err := addFieldInfo(typ, tinfo, &finfo); err != nil {
+ return nil, err
+ }
+ }
+ continue // 構造体埋め込みの処理後、次のフィールドへ
+ }
}
finfo, err := structFieldInfo(typ, &f)
このdiffは、getTypeInfo
関数内の埋め込みフィールド処理ロジックの核心を示しています。
-
変更前:
if t.Kind() != reflect.Struct { continue }
- これは、「もし埋め込みフィールドの型が構造体でなければ、この埋め込みフィールドの処理をスキップし、次のフィールドへ進む」という意味でした。このため、
MyInt
のような非構造体型の埋め込みは無視されていました。
- これは、「もし埋め込みフィールドの型が構造体でなければ、この埋め込みフィールドの処理をスキップし、次のフィールドへ進む」という意味でした。このため、
-
変更後:
if t.Kind() == reflect.Struct { ... continue }
- これは、「もし埋め込みフィールドの型が構造体であれば、その内部フィールドを再帰的に処理し、その後次のフィールドへ進む」という意味になります。
- 重要なのは、
if
ブロックの後にcontinue
があるため、埋め込みフィールドが構造体でない場合(例:MyInt
)、そのフィールドはif t.Kind() == reflect.Struct
の条件を満たさず、if
ブロック内のコードは実行されません。そして、continue
も実行されないため、処理はif f.Anonymous
ブロックの後の通常のフィールド処理ロジック(finfo, err := structFieldInfo(typ, &f)
から始まる部分)にフォールスルーします。 - このフォールスルーにより、非構造体型の埋め込みフィールドも、通常のフィールドと同様に
encoding/xml
によって適切に処理されるようになりました。
関連リンク
- Go言語の構造体埋め込みに関する公式ドキュメントやチュートリアル
encoding/xml
パッケージの公式ドキュメント- Goの
reflect
パッケージの公式ドキュメント