型と値の特性

値の表現

事前宣言された型(以下のインターフェースanyerrorを参照)、配列、および構造体の値は自己完結型です:そのような各値はそのデータのすべての完全なコピーを含み、そのような型の変数は値全体を格納します。たとえば、配列変数は配列のすべての要素のストレージ(変数)を提供します。それぞれのゼロ値は値の型に固有であり、決してnilではありません。

nilではないポインタ、関数、スライス、マップ、およびチャネルの値には、複数の値によって共有される可能性のある基礎となるデータへの参照が含まれています:

  • ポインタ値は、ポインタの基底型の値を保持する変数への参照です。
  • 関数値は、(場合によっては匿名の)関数とその環境への参照を含みます。
  • スライス値は、スライスの長さ、容量、および基底配列への参照を含みます。
  • マップまたはチャネル値は、マップまたはチャネルの実装固有のデータ構造への参照です。

インターフェース値は、インターフェースの動的型に応じて、自己完結型であるか、基礎となるデータへの参照を含むことがあります。事前宣言された識別子nilは、参照を含むことができる型のゼロ値です。

複数の値が基礎となるデータを共有する場合、ある値を変更すると別の値も変更される可能性があります。たとえば、スライスの要素を変更すると、配列を共有するすべてのスライスの基底配列のその要素が変更されます。

基底型

各型Tには基底型があります:もしTが事前宣言されたブール型、数値型、または文字列型、あるいは型リテラルの一つである場合、対応する基底型はT自身です。それ以外の場合、Tの基底型は、Tがその宣言で参照する型の基底型です。型パラメータの場合、それは常にインターフェースである型制約の基底型です。

type (
    A1 = string
    A2 = A1
)

type (
    B1 string
    B2 B1
    B3 []B1
    B4 B3
)

func f[P any](x P) {  }

stringA1A2B1、およびB2の基底型はstringです。[]B1B3、およびB4の基底型は[]B1です。Pの基底型はinterface{}です。

型の同一性

二つの型は同一(「同じ」)であるか、または異なるかのいずれかです。

名前付き型は常に他の型とは異なります。それ以外の場合、二つの型は、その基底型リテラルが構造的に等価である場合に同一です;つまり、それらは同じリテラル構造を持ち、対応するコンポーネントが同一の型を持ちます。詳細には:

  • 二つの配列型は、同一の要素型と同じ配列の長さを持つ場合に同一です。
  • 二つのスライス型は、同一の要素型を持つ場合に同一です。
  • 二つの構造体型は、同じフィールドのシーケンスを持ち、対応するフィールドのペアが同じ名前、同一の型、同一のタグを持ち、かつ両方が埋め込まれているか、両方が埋め込まれていない場合に同一です。異なるパッケージからのエクスポートされていないフィールド名は常に異なります。
  • 二つのポインタ型は、同一のベース型を持つ場合に同一です。
  • 二つの関数型は、同じ数のパラメータと結果値を持ち、対応するパラメータと結果の型が同一であり、かつ両方の関数が可変引数を持つか、両方とも持たない場合に同一です。パラメータと結果の名前は一致する必要はありません。
  • 二つのインターフェース型は、同じ型セットを定義する場合に同一です。
  • 二つのマップ型は、同一のキーと要素の型を持つ場合に同一です。
  • 二つのチャネル型は、同一の要素型と同じ方向を持つ場合に同一です。
  • 二つのインスタンス化された型は、それらの定義された型とすべての型引数が同一である場合に同一です。

以下の宣言が与えられた場合:

type (
    A0 = []string
    A1 = A0
    A2 = struct{ a, b int }
    A3 = int
    A4 = func(A3, float64) *A0
    A5 = func(x int, _ float64) *[]string

    B0 A0
    B1 []string
    B2 struct{ a, b int }
    B3 struct{ a, c int }
    B4 func(int, float64) *B0
    B5 func(x int, y float64) *A1

    C0 = B0
    D0[P1, P2 any] struct{ x P1; y P2 }
    E0 = D0[int, string]
)

これらの型は同一です:

A0, A1, and []string
A2 and struct{ a, b int }
A3 and int
A4, func(int, float64) *[]string, and A5

B0 and C0
D0[int, string] and E0
[]int and []int
struct{ a, b *B5 } and struct{ a, b *B5 }
func(x int, y float64) *[]string, func(int, float64) (result *[]string), and A5

B0B1は、それらが別々の型定義によって作成された新しい型であるため異なります;func(int, float64) *B0func(x int, y float64) *[]stringは、B0[]stringとは異なるため異なります;またP1P2は、それらが異なる型パラメータであるため異なります。D0[int, string]struct{ x int; y string }は、前者がインスタンス化された定義型であるのに対し、後者は型リテラルであるため異なります(ただし、それらは依然として代入可能です)。

代入可能性

Vの値xが型T変数代入可能である(「xTに代入可能」)のは、以下の条件のいずれかが適用される場合です:

  • VTが同一である。
  • VTが同一の基底型を持ち、型パラメータではなく、かつVまたはTの少なくとも一方が名前付き型ではない。
  • VTが同一の要素型を持つチャネル型であり、Vが双方向チャネルであり、かつVまたはTの少なくとも一方が名前付き型ではない。
  • Tがインターフェース型であり、型パラメータではなく、かつxT実装している。
  • xが事前宣言された識別子nilであり、Tがポインタ型、関数型、スライス型、マップ型、チャネル型、またはインターフェース型であり、型パラメータではない。
  • xが型Tの値によって表現可能な型付けされていない定数である。

さらに、xの型VまたはTが型パラメータである場合、xが型Tの変数に代入可能なのは、以下の条件のいずれかが適用される場合です:

  • xが事前宣言された識別子nilであり、Tが型パラメータであり、かつxTの型セット内のすべての型に代入可能である。
  • V名前付き型ではなく、Tが型パラメータであり、かつxTの型セット内のすべての型に代入可能である。
  • Vが型パラメータであり、Tが名前付き型ではなく、かつVの型セット内のすべての型の値がTに代入可能である。

表現可能性

定数 x は、型パラメータではない型 T の値によって表現可能であるのは、以下の条件のいずれかが適用される場合です:

  • xT によって決定される値の集合内にある。
  • T浮動小数点型であり、x がオーバーフローなしに T の精度に丸めることができる。丸めは IEEE 754 の偶数丸めルールを使用しますが、IEEE の負のゼロはさらに符号なしゼロに簡略化されます。定数値は決して IEEE の負のゼロ、NaN、または無限大にはならないことに注意してください。
  • T が複素数型であり、x成分 real(x)imag(x)T の成分型(float32 または float64)の値によって表現可能である。

T が型パラメータである場合、xT の型セット内のすべての型の値によって x が表現可能である場合に、型 T の値によって表現可能です。

x                   T           x は T の値によって表現可能である理由

'a'                 byte        97 はバイト値の集合内にある
97                  rune        rune は int32 のエイリアスであり、97 は 32 ビット整数の集合内にある
"foo"               string      "foo" は文字列値の集合内にある
1024                int16       1024 は 16 ビット整数の集合内にある
42.0                byte        42 は符号なし 8 ビット整数の集合内にある
1e10                uint64      10000000000 は符号なし 64 ビット整数の集合内にある
2.718281828459045   float32     2.718281828459045 は 2.7182817 に丸められ、float32 値の集合内にある
-1e-1000            float64     -1e-1000 は IEEE の -0.0 に丸められ、さらに 0.0 に簡略化される
0i                  int         0 は整数値である
(42 + 0i)           float32     42.0(虚部がゼロ)は float32 値の集合内にある
x                   T           x が T の値によって表現可能ではない理由

0                   bool        0 はブール値の集合内にない
'a'                 string      'a' はルーンであり、文字列値の集合内にない
1024                byte        1024 は符号なし 8 ビット整数の集合内にない
-1                  uint16      -1 は符号なし 16 ビット整数の集合内にない
1.1                 int         1.1 は整数値ではない
42i                 float32     (0 + 42i) は float32 値の集合内にない
1e1000              float64     1e1000 は丸めた後に IEEE の +Inf にオーバーフローする

メソッドセット

型のメソッドセットは、その型のオペランドに対して呼び出し可能なメソッドを決定します。すべての型には(空の可能性もある)メソッドセットが関連付けられています:

  • 定義型 T のメソッドセットは、レシーバ型 T で宣言されたすべてのメソッドから構成されます。
  • 定義型 T へのポインタのメソッドセット(ここで T はポインタでもインターフェースでもない)は、レシーバ *T または T で宣言されたすべてのメソッドの集合です。
  • インターフェース型のメソッドセットは、インターフェースの型セット内の各型のメソッドセットの交差です(結果のメソッドセットは通常、インターフェースで宣言されたメソッドの集合です)。

埋め込みフィールドを含む構造体(および構造体へのポインタ)にはさらに規則が適用され、構造体型のセクションで説明されています。その他の型には空のメソッドセットがあります。

メソッドセットでは、各メソッドは一意の非ブランクメソッド名を持つ必要があります。