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

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

このコミットは、Go言語の標準ライブラリ encoding/xml パッケージにおける、XMLマーシャリング(Goのデータ構造をXMLに変換する処理)の改善に関するものです。具体的には、Goの構造体内に非構造体型(例:intstringなどの基本型)が埋め込まれている場合に、それらを正しく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.Anonymoustrue のフィールド)を見つけると、その埋め込みフィールドの型が 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/xmlMyInt のような埋め込み非構造体型も正しくXML要素としてマーシャリングできるようになります。

marshal_test.go に追加されたテストケースは、この新しい振る舞いを検証するためのものです。EmbedInt 構造体に MyInt 型(int のエイリアス)を埋め込み、その構造体が期待通りのXML出力にマーシャリングされることを確認しています。

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

このコミットで変更された主要なファイルは以下の2つです。

  1. src/pkg/encoding/xml/marshal_test.go

    • 新しいテストケース EmbedIntMyInt が追加されました。
    • marshalTests スライスに、EmbedInt 型の値をマーシャリングするテストエントリが追加されました。これは、非構造体型の埋め込みが正しく処理されることを検証します。
  2. src/pkg/encoding/xml/typeinfo.go

    • getTypeInfo 関数内の、埋め込みフィールドを処理するロジックが変更されました。
    • 具体的には、埋め込みフィールドの型が構造体であるかどうかをチェックする条件 if t.Kind() != reflect.Structif 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 型をエイリアスした MyIntEmbedInt 構造体に埋め込み、その 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 パッケージの公式ドキュメント

参考にした情報源リンク

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

このコミットは、Go言語の標準ライブラリ encoding/xml パッケージにおける、XMLマーシャリング(Goのデータ構造をXMLに変換する処理)の改善に関するものです。具体的には、Goの構造体内に非構造体型(例:intstringなどの基本型)が埋め込まれている場合に、それらを正しく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.Anonymoustrue のフィールド)を見つけると、その埋め込みフィールドの型が 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/xmlMyInt のような埋め込み非構造体型も正しくXML要素としてマーシャリングできるようになります。

marshal_test.go に追加されたテストケースは、この新しい振る舞いを検証するためのものです。EmbedInt 構造体に MyInt 型(int のエイリアス)を埋め込み、その構造体が期待通りのXML出力にマーシャリングされることを確認しています。

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

このコミットで変更された主要なファイルは以下の2つです。

  1. src/pkg/encoding/xml/marshal_test.go

    • 新しいテストケース EmbedIntMyInt が追加されました。
    • marshalTests スライスに、EmbedInt 型の値をマーシャリングするテストエントリが追加されました。これは、非構造体型の埋め込みが正しく処理されることを検証します。
  2. src/pkg/encoding/xml/typeinfo.go

    • getTypeInfo 関数内の、埋め込みフィールドを処理するロジックが変更されました。
    • 具体的には、埋め込みフィールドの型が構造体であるかどうかをチェックする条件 if t.Kind() != reflect.Structif 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 型をエイリアスした MyIntEmbedInt 構造体に埋め込み、その 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 パッケージの公式ドキュメント

参考にした情報源リンク