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

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

このコミットは、Go言語のコンパイラ(gc)におけるインターフェース型に関する重要な変更を導入しています。具体的には、インターフェース内に他のインターフェース型を埋め込む機能(embedded interface types)を実装し、それによってコードの再利用性と表現力を向上させています。

コミット

commit b4af09ab569d72c7103b46f4e4833a4c7bc4ae78
Author: Russ Cox <rsc@golang.org>
Date:   Mon Feb 16 16:36:18 2009 -0800

    embedded interface types in interfaces.
    
    R=ken
    OCL=25072
    CL=25072
---
 src/cmd/gc/dcl.c | 36 +++++++++++++++++++++++++++++++++---\n src/cmd/gc/go.y  | 14 +++++++++++---\n 2 files changed, 44 insertions(+), 6 deletions(-)\n

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

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

元コミット内容

embedded interface types in interfaces.

R=ken
OCL=25072
CL=25072

変更の背景

このコミットは、Go言語の初期開発段階(2009年2月)に行われたもので、Go言語のインターフェースの設計と機能拡張の一環として導入されました。当時のGo言語はまだ公開されておらず、言語仕様が活発に議論・実装されていた時期です。

インターフェースはGo言語の重要な特徴の一つであり、ポリモーフィズムを実現するための強力なメカニズムです。しかし、複数のインターフェースが共通のメソッドセットを持つ場合や、あるインターフェースが別のインターフェースの機能を「継承」したい場合に、冗長なメソッド宣言が必要になるという課題がありました。

この「インターフェースの埋め込み」機能は、このような冗長性を排除し、より簡潔で表現力豊かなインターフェースの定義を可能にすることを目的としています。これにより、既存のインターフェースのメソッドセットを新しいインターフェースに簡単に含めることができるようになり、インターフェースの設計と利用がより柔軟になります。

前提知識の解説

Go言語のインターフェース

Go言語のインターフェースは、メソッドのシグネチャの集合を定義する型です。Goのインターフェースは「暗黙的」に実装されます。つまり、ある型がインターフェースで定義されたすべてのメソッドを実装していれば、その型はそのインターフェースを満たしていると見なされます。implementsキーワードのような明示的な宣言は不要です。

例:

type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

構造体の埋め込み (Struct Embedding)

Go言語には、構造体の中に他の構造体を「埋め込む」機能があります。これにより、埋め込まれた構造体のフィールドやメソッドが、外側の構造体のフィールドやメソッドであるかのようにアクセスできるようになります。これは、Goにおける「継承」に似たコードの再利用メカニズムとして機能します。

例:

type Base struct {
    ID int
}

func (b Base) GetID() int {
    return b.ID
}

type User struct {
    Base // Base構造体を埋め込み
    Name string
}

// User型のインスタンスからBaseのフィールドやメソッドに直接アクセスできる
// user := User{Base: Base{ID: 1}, Name: "Alice"}
// fmt.Println(user.GetID()) // 1

このコミットは、この構造体の埋め込みの概念をインターフェースにも拡張するものです。

技術的詳細

このコミットの主要な変更点は、Goコンパイラ(gc)がインターフェース定義内で他のインターフェース型を認識し、その埋め込まれたインターフェースのメソッドを自動的に新しいインターフェースのメソッドセットに含めるようにすることです。

具体的には、以下のコンパイラ内部の処理が変更されています。

  1. src/cmd/gc/go.y の変更:

    • go.y はGoコンパイラの字句解析器と構文解析器の定義ファイル(Yacc/Bison形式)です。
    • interfacedcl(インターフェース宣言)の文法が拡張され、latype(型名)を直接インターフェース宣言内に記述できるようになりました。これは、他のインターフェースを埋め込むための構文的な変更です。
    • 以前は、インターフェースの宣言はメソッドのリストのみを許可していましたが、この変更により、型名(つまり、他のインターフェース型)も許可されるようになりました。
  2. src/cmd/gc/dcl.c の変更:

    • dcl.c はGoコンパイラの宣言処理を担当するファイルです。
    • stotype 関数(おそらく "structure to type" の略で、ASTノードから型を構築する関数)が変更されています。
    • この関数内で、et == TINTER && n->left == N という条件が追加されています。これは、現在の処理対象がインターフェース型(TINTER)であり、かつノードがメソッド名を持たない(つまり、埋め込まれた型である)場合に該当します。
    • 埋め込まれたインターフェース型が検出されると、そのインターフェースが持つすべてのメソッドがループ処理され、新しいインターフェースのメソッドセットに「インライン化」されます。
    • この際、埋め込まれる型が実際にインターフェース型であるかどうかのチェック(n->type->etype != TINTER)が行われ、非インターフェース型が埋め込まれた場合にはエラーが報告されます。
    • また、埋め込まれたインターフェースに含まれるメソッドがエクスポートされていない(小文字で始まる)場合、つまり、異なるパッケージから埋め込まれたインターフェースが非エクスポートメソッドを持つ場合にもエラーが報告されます。これは、Goのエクスポートルール(大文字で始まる識別子のみがエクスポートされる)に準拠するためです。

この変更により、コンパイラはインターフェースの埋め込みを構文的に解釈し、セマンティックに処理できるようになります。結果として、ユーザーは以下のようなコードを書けるようになります。

type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

type ReadWriter interface {
    Reader // Readerインターフェースを埋め込み
    Writer // Writerインターフェースを埋め込み
}

ReadWriter インターフェースは、Read メソッドと Write メソッドの両方を持つことになります。

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

src/cmd/gc/dcl.c

--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -666,20 +666,50 @@ loop:
 	\tgoto next;\n \t}\n \n-\tif(n->op != ODCLFIELD || n->type == T)\n+\tif(n->op != ODCLFIELD)\n \t\tfatal(\"stotype: oops %N\\n\", n);\n \n+\tif(n->type == T) {\n+\t\t// assume error already printed\n+\t\tgoto next;\n+\t}\n+\n \tswitch(n->val.ctype) {\n \tcase CTSTR:\n+\t\tif(et != TSTRUCT)\n+\t\t\tyyerror(\"interface method cannot have annotation\");\n \t\tnote = n->val.u.sval;\n \t\tbreak;\n \tdefault:\n-\t\tyyerror(\"field annotation must be string\");\n+\t\tif(et != TSTRUCT)\n+\t\t\tyyerror(\"interface method cannot have annotation\");\n+\t\telse\n+\t\t\tyyerror(\"field annotation must be string\");\n \tcase CTxxx:\n \t\tnote = nil;\n \t\tbreak;\n \t}\n \n+\tif(et == TINTER && n->left == N) {\n+\t\t// embedded interface - inline the methods\n+\t\tif(n->type->etype != TINTER) {\n+\t\t\tyyerror(\"interface contains embedded non-interface %T\", t);\n+\t\t\tgoto next;\n+\t\t}\n+\t\tfor(t1=n->type->type; t1!=T; t1=t1->down) {\n+\t\t\tif(strcmp(t1->sym->package, package) != 0)\n+\t\t\t\tyyerror(\"embedded interface contains unexported method %S\", t1->sym);\n+\t\t\tf = typ(TFIELD);\n+\t\t\tf->type = t1->type;\n+\t\t\tf->width = BADWIDTH;\n+\t\t\tf->nname = newname(t1->sym);\n+\t\t\tf->sym = t1->sym;\n+\t\t\t*t = f;\n+\t\t\tt = &f->down;\n+\t\t}\n+\t\tgoto next;\n+\t}\n+\n \tf = typ(TFIELD);\n \tf->type = n->type;\n \tf->note = note;\n```

### `src/cmd/gc/go.y`

```c
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -1385,8 +1385,8 @@ embed:\n \t\tcontext = nil;\n \t}\n \n-interfacedcl:\n-\tnew_name \',\' interfacedcl\n+interfacedcl1:\n+\tnew_name \',\' interfacedcl1\n \t{\n \t\t$$ = nod(ODCLFIELD, $1, N);\n \t\t$$ = nod(OLIST, $$, $3);\n@@ -1397,6 +1397,14 @@ interfacedcl:\n \t\t$$->type = $2;\n \t}\n \n+interfacedcl:\n+\tinterfacedcl1\n+|\tlatype\n+\t{\n+\t\t$$ = nod(ODCLFIELD, N, N);\n+\t\t$$->type = oldtype($1);\n+\t}\n+\n indcl:\n \t\'(\' oarg_type_list \')\' fnres\n \t{\n```

## コアとなるコードの解説

### `src/cmd/gc/dcl.c` の変更点

*   **`stotype` 関数の変更**: この関数は、Goの型システムにおいて、構文解析されたノード(`Node`)から実際の型(`Type`)を構築する役割を担っています。特に、構造体フィールドやインターフェースメソッドの宣言を処理します。
*   **埋め込みインターフェースの検出と処理**:
    *   `if(et == TINTER && n->left == N)`: この条件が、インターフェース定義内で「埋め込まれた型」(メソッド名を持たない型)を検出する肝となる部分です。`et == TINTER` は現在の処理がインターフェース型を構築中であることを示し、`n->left == N` は現在のノードがメソッド名を持たないことを示します。
    *   `if(n->type->etype != TINTER)`: 埋め込まれようとしている型が実際にインターフェース型であるかを確認します。もしそうでなければ、`yyerror` でエラーを報告します。
    *   `for(t1=n->type->type; t1!=T; t1=t1->down)`: 埋め込まれたインターフェース(`n->type`)のメソッドリストをイテレートします。`t1` は個々のメソッドを表す型ノードです。
    *   `if(strcmp(t1->sym->package, package) != 0) && ... yyerror(...)`: 埋め込まれたインターフェースのメソッドが、現在のパッケージと異なるパッケージに属しているにもかかわらず、エクスポートされていない(シンボル名が小文字で始まる)場合にエラーを報告します。これは、Goの可視性ルールに則ったものです。
    *   `f = typ(TFIELD); ... *t = f; t = &f->down;`: 埋め込まれたインターフェースの各メソッドを、新しいインターフェースのメソッドリストに「フィールド」として追加します。`TFIELD` はコンパイラ内部でメソッドを表すために使用される型です。これにより、埋め込まれたインターフェースのメソッドが、あたかも新しいインターフェースで直接宣言されたかのように扱われます。

### `src/cmd/gc/go.y` の変更点

*   **`interfacedcl` ルールの拡張**:
    *   `interfacedcl1` という新しいルールが導入され、これは従来のメソッドリストの宣言を扱います。
    *   元の `interfacedcl` ルールが変更され、`interfacedcl1`(メソッドリスト)または `latype`(型名)のいずれかを受け入れるようになりました。
    *   `latype` は、Goの型名を指します。これにより、インターフェース定義内で他のインターフェースの型名を記述することが構文的に許可されます。
    *   `$$ = nod(ODCLFIELD, N, N); $$->type = oldtype($1);`: `latype` が検出された場合、これは埋め込みインターフェースとして扱われ、`ODCLFIELD` ノード(フィールド宣言ノード)として表現され、その型が埋め込まれるインターフェースの型として設定されます。`N` はノードが子を持たないことを示し、ここではメソッド名がないことを意味します。

これらの変更により、Goコンパイラはインターフェースの埋め込みという新しい構文を正しく解析し、そのセマンティクス(埋め込まれたインターフェースのメソッドを新しいインターフェースに含める)を適切に処理できるようになりました。

## 関連リンク

*   Go言語のインターフェースに関する公式ドキュメント: [https://go.dev/tour/methods/10](https://go.dev/tour/methods/10)
*   Go言語の埋め込みに関する公式ドキュメント: [https://go.dev/tour/methods/11](https://go.dev/tour/methods/11)
*   Go言語の初期のコミット履歴 (GitHub): [https://github.com/golang/go/commits/master?after=b4af09ab569d72c7103b46f4e4833a4c7bc4ae78+34&branch=master&path%5B%5D=src%2Fcmd%2Fgc](https://github.com/golang/go/commits/master?after=b4af09ab569d72c7103b46f4e4833a4c7bc4ae78+34&branch=master&path%5B%5D=src%2Fcmd%2Fgc)

## 参考にした情報源リンク

*   Go言語の公式ドキュメントおよびGo Tour
*   Go言語のGitHubリポジトリのコミット履歴
*   Yacc/Bisonの構文解析器の概念に関する一般的な知識
*   Go言語のコンパイラ(`gc`)のソースコード構造に関する一般的な理解# [インデックス 1684] ファイルの概要

このコミットは、Go言語のコンパイラ(`gc`)におけるインターフェース型に関する重要な変更を導入しています。具体的には、インターフェース内に他のインターフェース型を埋め込む機能(embedded interface types)を実装し、それによってコードの再利用性と表現力を向上させています。

## コミット

commit b4af09ab569d72c7103b46f4e4833a4c7bc4ae78 Author: Russ Cox rsc@golang.org Date: Mon Feb 16 16:36:18 2009 -0800

embedded interface types in interfaces.

R=ken
OCL=25072
CL=25072

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

[https://github.com/golang/go/commit/b4af09ab569d72c7103b46f4e4833a4c7bc4ae78](https://github.com/golang/go/commit/b4af09ab569d72c7103b46f4e4833a4c7bc4ae78)

## 元コミット内容

embedded interface types in interfaces.

R=ken OCL=25072 CL=25072


## 変更の背景

このコミットは、Go言語の初期開発段階(2009年2月)に行われたもので、Go言語のインターフェースの設計と機能拡張の一環として導入されました。当時のGo言語はまだ公開されておらず、言語仕様が活発に議論・実装されていた時期です。

インターフェースはGo言語の重要な特徴の一つであり、ポリモーフィズムを実現するための強力なメカニズムです。しかし、複数のインターフェースが共通のメソッドセットを持つ場合や、あるインターフェースが別のインターフェースの機能を「継承」したい場合に、冗長なメソッド宣言が必要になるという課題がありました。

この「インターフェースの埋め込み」機能は、このような冗長性を排除し、より簡潔で表現力豊かなインターフェースの定義を可能にすることを目的としています。これにより、既存のインターフェースのメソッドセットを新しいインターフェースに簡単に含めることができるようになり、インターフェースの設計と利用がより柔軟になります。

## 前提知識の解説

### Go言語のインターフェース

Go言語のインターフェースは、メソッドのシグネチャの集合を定義する型です。Goのインターフェースは「暗黙的」に実装されます。つまり、ある型がインターフェースで定義されたすべてのメソッドを実装していれば、その型はそのインターフェースを満たしていると見なされます。`implements`キーワードのような明示的な宣言は不要です。

例:
```go
type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

構造体の埋め込み (Struct Embedding)

Go言語には、構造体の中に他の構造体を「埋め込む」機能があります。これにより、埋め込まれた構造体のフィールドやメソッドが、外側の構造体のフィールドやメソッドであるかのようにアクセスできるようになります。これは、Goにおける「継承」に似たコードの再利用メカニズムとして機能します。

例:

type Base struct {
    ID int
}

func (b Base) GetID() int {
    return b.ID
}

type User struct {
    Base // Base構造体を埋め込み
    Name string
}

// User型のインスタンスからBaseのフィールドやメソッドに直接アクセスできる
// user := User{Base: Base{ID: 1}, Name: "Alice"}
// fmt.Println(user.GetID()) // 1

このコミットは、この構造体の埋め込みの概念をインターフェースにも拡張するものです。

技術的詳細

このコミットの主要な変更点は、Goコンパイラ(gc)がインターフェース定義内で他のインターフェース型を認識し、その埋め込まれたインターフェースのメソッドを自動的に新しいインターフェースのメソッドセットに含めるようにすることです。

具体的には、以下のコンパイラ内部の処理が変更されています。

  1. src/cmd/gc/go.y の変更:

    • go.y はGoコンパイラの字句解析器と構文解析器の定義ファイル(Yacc/Bison形式)です。
    • interfacedcl(インターフェース宣言)の文法が拡張され、latype(型名)を直接インターフェース宣言内に記述できるようになりました。これは、他のインターフェースを埋め込むための構文的な変更です。
    • 以前は、インターフェースの宣言はメソッドのリストのみを許可していましたが、この変更により、型名(つまり、他のインターフェース型)も許可されるようになりました。
  2. src/cmd/gc/dcl.c の変更:

    • dcl.c はGoコンパイラの宣言処理を担当するファイルです。
    • stotype 関数(おそらく "structure to type" の略で、ASTノードから型を構築する関数)が変更されています。
    • この関数内で、et == TINTER && n->left == N という条件が追加されています。これは、現在の処理対象がインターフェース型(TINTER)であり、かつノードがメソッド名を持たない(つまり、埋め込まれた型である)場合に該当します。
    • 埋め込まれたインターフェース型が検出されると、そのインターフェースが持つすべてのメソッドがループ処理され、新しいインターフェースのメソッドセットに「インライン化」されます。
    • この際、埋め込まれる型が実際にインターフェース型であるかどうかのチェック(n->type->etype != TINTER)が行われ、非インターフェース型が埋め込まれた場合にはエラーが報告されます。
    • また、埋め込まれたインターフェースに含まれるメソッドがエクスポートされていない(小文字で始まる)場合、つまり、異なるパッケージから埋め込まれたインターフェースが非エクスポートメソッドを持つ場合にもエラーが報告されます。これは、Goのエクスポートルール(大文字で始まる識別子のみがエクスポートされる)に準拠するためです。

この変更により、コンパイラはインターフェースの埋め込みを構文的に解釈し、セマンティックに処理できるようになります。結果として、ユーザーは以下のようなコードを書けるようになります。

type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

type ReadWriter interface {
    Reader // Readerインターフェースを埋め込み
    Writer // Writerインターフェースを埋め込み
}

ReadWriter インターフェースは、Read メソッドと Write メソッドの両方を持つことになります。

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

src/cmd/gc/dcl.c

--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -666,20 +666,50 @@ loop:
 	\tgoto next;\n \t}\n \n-\tif(n->op != ODCLFIELD || n->type == T)\n+\tif(n->op != ODCLFIELD)\n \t\tfatal(\"stotype: oops %N\\n\", n);\n \n+\tif(n->type == T) {\n+\t\t// assume error already printed\n+\t\tgoto next;\n+\t}\n+\n \tswitch(n->val.ctype) {\n \tcase CTSTR:\n+\t\tif(et != TSTRUCT)\n+\t\t\tyyerror(\"interface method cannot have annotation\");\n \t\tnote = n->val.u.sval;\n \t\tbreak;\n \tdefault:\n-\t\tyyerror(\"field annotation must be string\");\n+\t\tif(et != TSTRUCT)\n+\t\t\tyyerror(\"interface method cannot have annotation\");\n+\t\telse\n+\t\t\tyyerror(\"field annotation must be string\");\n \tcase CTxxx:\n \t\tnote = nil;\n \t\tbreak;\n \t}\n \n+\tif(et == TINTER && n->left == N) {\n+\t\t// embedded interface - inline the methods\n+\t\tif(n->type->etype != TINTER) {\n+\t\t\tyyerror(\"interface contains embedded non-interface %T\", t);\n+\t\t\tgoto next;\n+\t\t}\n+\t\tfor(t1=n->type->type; t1!=T; t1=t1->down) {\n+\t\t\tif(strcmp(t1->sym->package, package) != 0)\n+\t\t\t\tyyerror(\"embedded interface contains unexported method %S\", t1->sym);\n+\t\t\tf = typ(TFIELD);\n+\t\t\tf->type = t1->type;\n+\t\t\tf->width = BADWIDTH;\n+\t\t\tf->nname = newname(t1->sym);\n+\t\t\tf->sym = t1->sym;\n+\t\t\t*t = f;\n+\t\t\tt = &f->down;\n+\t\t}\n+\t\tgoto next;\n+\t}\n+\n \tf = typ(TFIELD);\n \tf->type = n->type;\n \tf->note = note;\n```

### `src/cmd/gc/go.y`

```c
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -1385,8 +1385,8 @@ embed:\n \t\tcontext = nil;\n \t}\n \n-interfacedcl:\n-\tnew_name \',\' interfacedcl\n+interfacedcl1:\n+\tnew_name \',\' interfacedcl1\n \t{\n \t\t$$ = nod(ODCLFIELD, $1, N);\n \t\t$$ = nod(OLIST, $$, $3);\n@@ -1397,6 +1397,14 @@ interfacedcl:\n \t\t$$->type = $2;\n \t}\n \n+interfacedcl:\n+\tinterfacedcl1\n+|\tlatype\n+\t{\n+\t\t$$ = nod(ODCLFIELD, N, N);\n+\t\t$$->type = oldtype($1);\n+\t}\n+\n indcl:\n \t\'(\' oarg_type_list \')\' fnres\n \t{\n```

## コアとなるコードの解説

### `src/cmd/gc/dcl.c` の変更点

*   **`stotype` 関数の変更**: この関数は、Goの型システムにおいて、構文解析されたノード(`Node`)から実際の型(`Type`)を構築する役割を担っています。特に、構造体フィールドやインターフェースメソッドの宣言を処理します。
*   **埋め込みインターフェースの検出と処理**:
    *   `if(et == TINTER && n->left == N)`: この条件が、インターフェース定義内で「埋め込まれた型」(メソッド名を持たない型)を検出する肝となる部分です。`et == TINTER` は現在の処理がインターフェース型を構築中であることを示し、`n->left == N` は現在のノードがメソッド名を持たないことを示します。
    *   `if(n->type->etype != TINTER)`: 埋め込まれようとしている型が実際にインターフェース型であるかを確認します。もしそうでなければ、`yyerror` でエラーを報告します。
    *   `for(t1=n->type->type; t1!=T; t1=t1->down)`: 埋め込まれたインターフェース(`n->type`)のメソッドリストをイテレートします。`t1` は個々のメソッドを表す型ノードです。
    *   `if(strcmp(t1->sym->package, package) != 0) && ... yyerror(...)`: 埋め込まれたインターフェースのメソッドが、現在のパッケージと異なるパッケージに属しているにもかかわらず、エクスポートされていない(シンボル名が小文字で始まる)場合にエラーを報告します。これは、Goの可視性ルールに則ったものです。
    *   `f = typ(TFIELD); ... *t = f; t = &f->down;`: 埋め込まれたインターフェースの各メソッドを、新しいインターフェースのメソッドリストに「フィールド」として追加します。`TFIELD` はコンパイラ内部でメソッドを表すために使用される型です。これにより、埋め込まれたインターフェースのメソッドが、あたかも新しいインターフェースで直接宣言されたかのように扱われます。

### `src/cmd/gc/go.y` の変更点

*   **`interfacedcl` ルールの拡張**:
    *   `interfacedcl1` という新しいルールが導入され、これは従来のメソッドリストの宣言を扱います。
    *   元の `interfacedcl` ルールが変更され、`interfacedcl1`(メソッドリスト)または `latype`(型名)のいずれかを受け入れるようになりました。
    *   `latype` は、Goの型名を指します。これにより、インターフェース定義内で他のインターフェースの型名を記述することが構文的に許可されます。
    *   `$$ = nod(ODCLFIELD, N, N); $$->type = oldtype($1);`: `latype` が検出された場合、これは埋め込みインターフェースとして扱われ、`ODCLFIELD` ノード(フィールド宣言ノード)として表現され、その型が埋め込まれるインターフェースの型として設定されます。`N` はノードが子を持たないことを示し、ここではメソッド名がないことを意味します。

これらの変更により、Goコンパイラはインターフェースの埋め込みという新しい構文を正しく解析し、そのセマンティクス(埋め込まれたインターフェースのメソッドを新しいインターフェースに含める)を適切に処理できるようになりました。

## 関連リンク

*   Go言語のインターフェースに関する公式ドキュメント: [https://go.dev/tour/methods/10](https://go.dev/tour/methods/10)
*   Go言語の埋め込みに関する公式ドキュメント: [https://go.dev/tour/methods/11](https://go.dev/tour/methods/11)
*   Go言語の初期のコミット履歴 (GitHub): [https://github.com/golang/go/commits/master?after=b4af09ab569d72c7103b46f4e4833a4c7bc4ae78+34&branch=master&path%5B%5D=src%2Fcmd%2Fgc](https://github.com/golang/go/commits/master?after=b4af09ab569d72c7103b46f4e4833a4c7bc4ae78+34&branch=master&path%5B%5D=src%2Fcmd%2Fgc)

## 参考にした情報源リンク

*   Go言語の公式ドキュメントおよびGo Tour
*   Go言語のGitHubリポジトリのコミット履歴
*   Yacc/Bisonの構文解析器の概念に関する一般的な知識
*   Go言語のコンパイラ(`gc`)のソースコード構造に関する一般的な理解
*   Web検索: "Go language embedded interface types in interfaces 2009"