イントロダクション#
これは Go 言語のリファレンスマニュアルです。詳細情報や他のドキュメントについては、golang.org を訪問してください。
Go は、システムプログラミングを考慮して設計された汎用プログラミング言語です。強い型付けがあり、ガーベジコレクション機構を持ち、並行プログラミングをネイティブにサポートしています。Go プログラムは、依存関係を効率的に管理するために、1 つまたは複数のパッケージで構成されています。
Go の構文は簡潔で規則的であり、これにより自動化ツールがコードを簡単に解析できます。たとえば、統合開発環境などです。
文法#
構文は拡張バッカス - ナウア形式を使用しています。
Production = production_name "=" [ Expression ] "." .
Expression = Alternative { "|" Alternative } .
Alternative = Term { Term } .
Term = production_name | token [ "…" token ] | Group | Option | Repetition .
Group = "(" Expression ")" .
Option = "[" Expression "]" .
Repetition = "{" Expression "}" .
生成規則は、語彙単位と以下の演算子から構成される式です(優先順位は増加します):
| または
() グループ化
[] オプション(0 または 1 回出現)
{} 繰り返し(0 から n 回出現)
小文字の生成規則名は語彙単位と区別するために使用されます。非終端記号はキャメルケースを使用します。語彙単位は二重引用符またはバッククォートで構成されます。
a...b
は a
から b
の間の任意の文字を表します。省略記号 ...
は、より詳細な列挙やコードスニペットの省略を示すために規則内でも使用できます。文字 ...
は Go 言語の語彙単位ではありません。
ソースコード表現#
Go のソースコードは UTF-8 エンコーディングの Unicode テキストを使用します。ただし、完全に正規化されているわけではなく、単音符号のコードポイントと同じ文字と音標で構成されたコードポイントは異なります。前者は 2 つのコードポイントと見なされます。簡単に言えば、ドキュメントはソースコードテキスト内で非正規の用語文字を使用して Unicode コードポイントを表現します。
各コードポイントは異なります。同じ文字の大文字と小文字は異なる文字を表します。
実装制限:他のツールとの互換性のため、コンパイラは UTF-8 エンコーディングのソーステキスト内に NUL 文字(U+0000)が出現することを許可しません。
実装制限:他のツールとの互換性のため、ソーステキストが UTF-8 エンコーディングのバイトオーダーマーク(U+FEFF)で始まる場合、コンパイラはそれを無視します。バイトオーダーマークはソーステキストのどの位置にも出現すべきではありません。
文字#
これらの単語は Unicode 文字のカテゴリを表します:
newline = /* Unicode コードポイント U+000A */ .
unicode_char = /* 改行以外の任意の Unicode コードポイント */ .
unicode_letter = /* 1 文字("Letter")タイプの Unicode コードポイント */ .
unicode_digit = /* 1 数字("Number, decimal digit")タイプの Unicode コードポイント */ .
Unicode 8.0 標準の第 4.5 章「一般カテゴリ」で文字のカテゴリが定義されています。Go は Lu、Li、Lt、Lm または Lo を Unicode 文字として処理でき、数字文字セット Nd を Unicode 数字として処理できます。
文字と数字#
アンダースコア _
(U+005F)は文字として扱われます:
letter = unicode_letter | "_" .
decimal_digit = "0" … "9" .
octal_digit = "0" … "7" .
hex_digit = "0" … "9" | "A" … "F" | "a" … "f" .
語彙要素#
コメント#
コメントはプログラムの説明文書です。Go には 2 つの形式があります:
- 単一行コメントは
//
から行末まで続きます。 - 複数行コメントは
/*
から*/
まで続きます。
コメントは他のコメント、文字列、rune のリテラル内にネストできません。改行を含まない複数行コメントは空白で接続され、他の場合は各コメントが新しい行で始まります。
語彙要素#
語彙要素は Go 言語の語彙を構成します。4 種類のタイプがあります:識別子、キーワード、演算子 / 句読点、リテラル。空白は空白(U+0020)、水平タブ(U+0009)、改行(U+000D)、または改行(U+000A)である場合があります。空白自体は無視され、一般的に異なる語彙要素を区別するために使用されます。改行またはファイル終端符(EOF)は、ソースコードの行末またはファイル末尾にセミコロンを追加するトリガーになる場合があります。ソースコードの語彙要素を分解する過程で、現在有効な語彙要素を形成できる最長の文字列シーケンスが次の語彙要素として扱われます。
セミコロン#
正式な構文では多くの生成規則でセミコロン ";" が終端子として使用されます。Go プログラムでは、以下の 2 つのルールに従ってほとんどのセミコロンが省略されます:
- 行の最後の語彙要素が以下の要素のいずれかである場合、自動的にセミコロンが補完されます:
-
識別子。
-
整数、浮動小数点数、虚数、rune または文字列リテラル。
-
キーワード
break
、continue
、fallthrough
、return
のいずれか。 -
演算子 / 句読点
++
、--
、)
、]
、}
のいずれか。
- 複雑な文が独占的に 1 行を占めることをサポートするために、")" または "}" に隣接するセミコロンが省略されます。
慣用的な用途を反映するために、この文書のすべての例は、上記のルールに基づいてセミコロンを省略しています。
識別子#
識別子はプログラムのエンティティ単位を表します。たとえば、変数、型。識別子は 1 つ以上の文字と数字で構成されます。識別子の最初の文字は文字でなければなりません。
identifier = letter { letter | unicode_digit } .
a
_x9
ThisVariableIsExported
αβ
Go はいくつかの識別子を事前に定義しています。
キーワード#
以下のキーワードは予約されており、識別子として使用できません:
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
演算子と句読点#
以下の文字列は演算子(代入演算子を含む)と句読点を表すために使用されます:
+ & += &= && == != ( )
- | -= |= || < <= [ ]
* ^ *= ^= <- > >= { }
/ << /= <<= ++ = := , ;
% >> %= >>= -- ! ... . :
&^ &^=
整数リテラル#
整数リテラルは数字のシーケンスであり、整数定数に相当します。接頭辞を使用して非小数進数を指定できます:0 は 8 進数、0x/0X は 16 進数を表します。16 進数リテラルでは、文字 a-f および A-F はそれぞれ数字 10-15 を表します。
int_lit = decimal_lit | octal_lit | hex_lit .
decimal_lit = ( "1" … "9" ) { decimal_digit } .
octal_lit = "0" { octal_digit } .
hex_lit = "0" ( "x" | "X" ) hex_digit { hex_digit } .
42
0600
0xBadFace
170141183460469231731687303715884105727
浮動小数点リテラル#
浮動小数点リテラルは小数であり、浮動小数点数定数に相当します。整数部分、小数点、小数部分、指数部分で構成されます。整数部分と小数部分は小数点でリンクされます。指数部分は e
/ E
文字の後に符号付き指数が続きます。整数部分と小数部分のいずれかを省略できます。小数点と指数部分のいずれかを省略できます。
float_lit = decimals "." [ decimals ] [ exponent ] |
decimals exponent |
"." decimals [ exponent ] .
decimals = decimal_digit { decimal_digit } .
exponent = ( "e" | "E" ) [ "+" | "-" ] decimals .
0.
72.40
072.40 // == 72.40
2.71828
1.e+0
6.67428e-11
1E6
.25
.12345E+5
虚数リテラル#
虚数リテラルは小数であり、複素数定数の虚数部分に相当します。浮動小数点数または整数の後に小文字の i が続きます。
imaginary_lit = (decimals | float_lit) "i" .
0i
011i // == 11i
0.i
2.71828i
1.e+0i
6.67428e-11i
1E6i
.25i
.12345E+5i
rune リテラル#
rune 型リテラルは 1 つの rune 定数に相当します。これは Unicode コードポイントを表す整数です。rune 型リテラルは、単一引用符で囲まれた 1 つ以上の文字として表されます。たとえば、'x' や '\n' です。単一引用符内では改行文字とエスケープされていない単一引用符以外の文字を直接表示できます。単一引用符で囲まれた文字の値は、Unicode コードでの値と等しく、バックスラッシュで始まる複数の文字列は、値をさまざまな形式に変換します。
単一文字を表すために引用符を使用するのが最も簡単な方法です。Go のソーステキストは UTF-8 エンコーディングであり、1 つの整数は複数の UTF-8 バイトを表す場合があります。たとえば、 'a' は単一バイトで文字 a を表し、Unicode コード U+0061、値 0x61 ですが、 'ä' は二重バイトで分音符の a を表し、Unicode コード U+00E4、値 0xe4 です。
バックスラッシュは任意の値を ASCII テキストにエンコードできます。整数値を数値定数として表すには 4 つの方法があります:\x
の後に 2 つの 16 進数;\u
の後に 4 つの 16 進数;\U
の後に 8 つの 16 進数。 \
の後に 3 つの 8 進数。各場合において、リテラルの整数値を表すために対応する基数を使用します。
これら 4 つの方法はすべて整数を表しますが、有効範囲は異なります。8 進数は 0 - 255 の範囲内の整数のみを表すことができます。16 進数は要件を満たすことができます。\u
と \U
は Unicode コードポイントを表すことができますが、その中のいくつかの値は無効です。特に 0x10FFFF 以上の値です。
バックスラッシュは以下の文字と組み合わせると特別な意味を持ちます:
\a U+0007 アラートまたはベル
\b U+0008 バックスペース
\f U+000C フォームフィード
\n U+000A 改行または新しい行
\r U+000D キャリッジリターン
\t U+0009 水平タブ
\v U+000b 垂直タブ
\\ U+005c バックスラッシュ
\' U+0027 単一引用符 (rune リテラル内でのみ有効)
\" U+0022 二重引用符 (文字列リテラル内でのみ有効)
バックスラッシュで始まる他のすべてのシーケンスは、rune の規則内では無効です。
rune_lit = "'" ( unicode_value | byte_value ) "'" .
unicode_value = unicode_char | little_u_value | big_u_value | escaped_char .
byte_value = octal_byte_value | hex_byte_value .
octal_byte_value = `\` octal_digit octal_digit octal_digit .
hex_byte_value = `\` "x" hex_digit hex_digit .
little_u_value = `\` "u" hex_digit hex_digit hex_digit hex_digit .
big_u_value = `\` "U" hex_digit hex_digit hex_digit hex_digit
hex_digit hex_digit hex_digit hex_digit .
escaped_char = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `"` ) .
'a'
'ä'
'本'
'\t'
'\000'
'\007'
'\377'
'\x07'
'\xff'
'\u12e4'
'\U00101234'
'\'' // 単一引用符を含む rune リテラル
'aa' // 無効: 文字が多すぎます
'\xa' // 無効: 16 進数が不足しています
'\0' // 無効: 8 進数が不足しています
'\uDFFF' // 無効: サロゲート半分
'\U00110000' // 無効: 不正な Unicode コードポイント
文字列リテラル#
文字列リテラルは、文字列定数を取得するための文字列を表します。2 つの形式があります:生文字列リテラルと解釈型文字列リテラル。
生文字列はバッククォートで囲まれています(foo
)。文字列内のバッククォート以外の他の文字はすべて表示されます。生文字列はバッククォートの間の(デフォルトの UTF-8 エンコーディングの)文字で構成されています。その値は、引用符内のすべての文字が解釈されず(デフォルトの UTF-8 エンコーディング)、特にバックスラッシュは文字列内で特別な意味を持たず、文字列内の改行文字が保持されます。生文字列の値では、キャリッジリターン '\r' 文字が破棄されます。
解釈型文字列は、二重引用符の間の文字で構成されています("bar")。改行文字と二重引用符以外の他の文字はすべて表示されます。二重引用符の間のテキストはリテラルの値を構成します。バックスラッシュのエスケープ規則は rune リテラルと基本的に同じです(違いは \’ が無効で、" が有効です)。3 桁の 8 進数(\nnn)と 2 桁の 16 進数(\xnn)エスケープシーケンスの値は、対応する文字列のバイトを表します。他のエスケープシーケンスは、各文字の UTF-8 エンコーディングを表します(複数バイトの可能性があります)。したがって、文字列 \377 と \xFF は、値が 0xFF=255 の単一バイトを表し、 ÿ
, \u00FF
, \U000000FF
および \xc3\xbf
は、UTF-8 エンコーディング文字 U+00FF の 2 バイト 0xc3 0xbf を表します。
string_lit = raw_string_lit | interpreted_string_lit .
raw_string_lit = "`" { unicode_char | newline } "`" .
interpreted_string_lit = `"` { unicode_value | byte_value } `"` .
`abc` // "abc" と等価
`\n
\n` // "\\n\n\\n" と等価
"\n"
"\"" // `"` と等価
"Hello, world!\n"
"日本語"
"\u65e5本\U00008a9e"
"\xff\u00FF"
"\uD800" // 無効: サロゲート半分
"\U00110000" // 無効: 無効な Unicode コードポイント
これらの例は同じ文字列を表します:
"日本語" // UTF-8 テキスト
`日本語` // UTF-8 テキストを生リテラルとして
"\u65e5\u672c\u8a9e" // 確定的な Unicode コードポイント
"\U000065e5\U0000672c\U00008a9e" // 確定的な Unicode コードポイント
"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" // 確定的な UTF-8 バイト
ソースコード内で 2 つのコードポイントを使用して 1 つの文字を表す場合、たとえば、音符付きの文字を rune に置くとエラーが発生します(それは単一のコードポイントではありません)。文字列内では 2 つのコードポイントが表示されます。
定数#
定数は、ブール型、rune 型、整数型、浮動小数点型、複素型、文字列型に分けられます。rune、整数型、浮動小数点型、複素型は総称して数値定数と呼ばれます。
定数の値は、rune リテラル、整数リテラル、浮動小数点リテラル、虚数リテラル、文字列リテラル、定数を表す識別子、定数式、定数に変換される型変換の結果、およびいくつかの戻り値が定数である組み込み関数(任意の値を受け取る unsafe.Sizeof
、部分式を受け取る cap
または len
、虚数定数を受け取る real
と imag
、数値定数を受け取る complex
)によって表されます。ブール型の値は、事前定義された定数 true
または false
であり、事前定義された識別子 iota
は整数定数を表します。
一般的に、複素数定数は定数式の一形態です。定数式の章で詳しく説明します。
数値定数は任意の精度の確定値を表すことができ、オーバーフローすることはありません。したがって、非 0、無限大、非数値の値を表す定数は存在しません。
定数は型を指定することも、指定しないこともできます。リテラル定数、true
、false
、iota
、および無型定数操作のみを含む定数式は無型です。
定数は、定数宣言や変換時に明示的に特定の型を指定することができ、変数宣言、代入、または式操作のオペランドとして暗黙的に特定の型を指定することもできます。定数の値とその型が一致しない場合、エラーが発生します。
無型定数はデフォルトの型を持ち、この型は定数を使用する際の文脈に応じて暗黙的に変換されます。たとえば、短い変数宣言 i := 0
では、i の型は指定されていません。無型定数のデフォルトの型は bool
、rune
、int
、float64
、complex128
または string
であり、具体的にどの型を選択するかは定数の値によって決まります。
実装制限:数値定数は Go で任意の精度ですが、コンパイラは内部で精度を制限します。これは、各コンパイラ実装が次のことを保証する必要があることを意味します:
-
整数定数は少なくとも 256 ビットである必要があります。
-
浮動小数点数定数(複素数定数を含む)は、少なくとも 256 ビットの主部と少なくとも 16 ビットの符号付き指数部を保証する必要があります。
-
指定された整数の精度を表現できない場合はエラーをスローします。
-
浮動小数点数または複素数がオーバーフローした場合はエラーをスローします。
-
精度制限のために浮動小数点数または複素数を表現できない場合は丸めを行います。
これらの要件は、リテラル定数と定数式の結果の両方に適用されます。
変数#
変数は値を保存するための位置です。変数の型によって異なる値を保存できます。
変数宣言、関数の引数と戻り値、宣言された関数のシグネチャ、函数字面値は、命名された変数のストレージスペースを予約します。組み込みの new
関数を呼び出すか、複合リテラルのアドレスを取得すると、実行時に変数にストレージスペースが割り当てられます。この匿名変数は(おそらく暗黙的に)ポインタを介して間接的に参照されます。
配列、スライス、構造体型の変数は、内部に多くの要素やフィールドを含み、これらの要素やフィールドには直接アクセスできます。配列やスライスの各要素の動作は、個別の変数と基本的に同じです。
変数の静的型は、変数宣言、new
に提供された型、複合リテラル、構造体変数宣言の要素型など、いくつかの方法で決定されます。new
または型初期化を介して決定されます。インターフェース型の変数にも明示的な動的型があり、この動的型は実行時に変数に具体的な値の型を割り当てます(特例:事前に宣言された nil は無型です)。動的型はプログラムの実行中に異なる場合がありますが、インターフェース変数の値は同じ静的型の変数に割り当てることができます。
var x interface{} // x の静的型は interface{} 値は nil
var v *T // v の静的型は *T 値は nil
x = 42 // x の動的型は int 値は 42
x = v // x の動的型は *T 値は (*T)(nil)
式内で変数を使用すると、変数の値を取得できます。この値は、変数が最後に割り当てられた値です。変数に値が割り当てられていない場合、その値はその型のゼロ値です。
型#
型は、値と値に対する操作およびメソッドの集合です。型は型名を使用して表すことができます。型にはさまざまな表現形式があります。型名が存在する場合は型名を使用して表すことができ、既存の型を組み合わせて生成された型リテラルを使用することもできます。
Type = TypeName | TypeLit | "(" Type ")" .
TypeName = identifier | QualifiedIdent .
TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
SliceType | MapType | ChannelType .
Go は特定の型名を事前に宣言しています。また、型宣言を導入しています。複合型(配列、構造体、ポインタ、関数、インターフェース、スライス、マップ、チャネル)は、その型リテラルを使用できます。
各型 T には基底型があります。T が事前定義された型または型リテラルである場合、基底型はそれ自体です。それ以外の場合、T の基底型は、型宣言時に参照された型です。
type (
A1 = string
A2 = A1
)
type (
B1 string
B2 B1
B3 []B1
B4 B3
)
string
、A1
、A2
、B1
、B2
の基底型は string
です。[]B1
、B3
、B4
の基底型は []B1
です。
メソッドセット#
型には関連するメソッドセットがある場合があります。インターフェース型のメソッドセットは自分自身を使用して表すことができます。他の型の場合、型 T のメソッドセットは、すべての受信者型が T のメソッドで構成されます。対応するポインタ型 *T のメソッドセットは、すべての受信者型が T または *T のメソッドで構成されます。構造体型で埋め込みフィールドを含む場合、メソッドセットにはさらに多くのメソッドが含まれる場合があります。詳細については、構造体型の章を参照してください。他の型のメソッドセットは空です。メソッドセット内の各メソッドには、ユニークで空でないメソッド名があります。
型のメソッドセットは、型が実装するインターフェースと、型を受信者として呼び出すことができるメソッドを決定するために使用されます。
ブール型#
ブール型は、事前定義された定数 true
と false
を表すブール値の集合です。事前定義されたブール型は bool
です。これは型宣言によって作成されます。
数字型#
数字型は、整数型と浮動小数点型のすべての値の集合に相当します。事前定義された数字型には次のものがあります:
uint8 8 ビット符号なし整数の集合 (0 から 255)
uint16 16 ビット符号なし整数の集合 (0 から 65535)
uint32 32 ビット符号なし整数の集合 (0 から 4294967295)
uint64 64 ビット符号なし整数の集合 (0 から 18446744073709551615)
int8 8 ビット符号付き整数の集合 (-128 から 127)
int16 16 ビット符号付き整数の集合 (-32768 から 32767)
int32 32 ビット符号付き整数の集合 (-2147483648 から 2147483647)
int64 64 ビット符号付き整数の集合 (-9223372036854775808 から 9223372036854775807)
float32 IEEE-754 32 ビット浮動小数点数の集合
float64 IEEE-754 64 ビット浮動小数点数の集合
complex64 実部と虚部がともに float32 の複素数の集合
complex128 実部と虚部がともに float64 の複素数の集合
byte uint8 のエイリアス
rune int32 のエイリアス
n ビット整数の値は n ビット幅を持ち、補数で表されます。
以下のいくつかの事前定義された型は、具体的なプラットフォームによって指定された長さを持ちます:
uint 32 または 64 ビット
int および uint はビット数が同じ
uintptr ポインタ値を格納できる符号なし整数
移植性の問題を避けるために、uint8 のエイリアス byte と int32 のエイリアス rune を除いて、他のすべての数字型は型宣言によって定義されます。式内で異なる数字型を使用する場合は、型変換が必要です。たとえば、int32 と int は同じ型ではありません。たとえ指定されたプラットフォームで等しいとしても。
文字列型#
文字列型は文字列の値の型を表します。文字列の値はバイトのシーケンス(空である可能性があります)です。文字列が作成されると、その値を変更することはできません。事前定義された文字列型は string
であり、型宣言によって定義されています。
組み込み関数 len
を使用して文字列の長さを取得できます。文字列が定数である場合、その長さはコンパイル時にも定数になります。数字のインデックス 0~len (s)-1 を使用して文字列のバイトにアクセスできます。文字列のアドレスを取得することは無効な操作です。もし s[i]
が文字列の i 番目のバイトであれば、&s[i]
は無効です。
配列型#
配列は、単一の型の要素のシーケンスであり、この単一の型を要素型と呼びます。要素の個数は要素の長さを示し、常に負の数ではありません。
ArrayType = "[" ArrayLength "]" ElementType .
ArrayLength = Expression .
ElementType = Type .
長さは配列型の一部であり、int 型の非負定数です。組み込み関数 len
を使用して配列の長さを取得できます。要素はインデックス 0~len(a)-1
を使用してアクセスできます。配列は一般的に一次元ですが、多次元でも構いません。
[32]byte
[2*N] struct { x, y int32 }
[1000]*float64
[3][5]int
[2][2][2]float64 // [2]([2]([2]float64)) と同じ
スライスタイプ#
スライスは、基になる配列の連続したセグメントを記述し、連続したセグメント内の要素へのアクセスを提供します。スライスタイプは、要素型の配列のすべてのスライスの集合を表します。初期化されていないスライスは nil で表されます。
SliceType = "[" "]" ElementType .
配列と同様に、スライスはインデックスでアクセスでき、長さを持ち、スライスの長さは組み込みの len
関数を使用して取得できます。配列とは異なり、スライスの長さは実行時に変更可能です。インデックス 0~len(s)-1
を使用してスライス内の要素にアクセスできます。スライスのインデックスは、基になる配列のインデックスよりも小さい場合があります。
スライスが初期化されると、スライス内の要素を保存するための基になる配列が作成されます。スライスと基になる配列の他のスライスは、同じストレージスペースを共有します。異なる配列は常に異なるストレージスペースを持ちます。
スライスの基になる配列は、スライスの末尾を超えて拡張される場合があります。スライスの容量は、スライスの現在の長さに、配列内のスライスがまだ使用していない長さを加えたものです。元のスライスから、長さと容量が等しいスライスを切り出すことができます。スライスの容量は、組み込みの cap(a)
関数を使用して取得できます。関数 make
を使用して、T 型の新しいスライスを作成できます。
組み込み関数 make
を使用して、指定された要素型 T のスライスを作成できます。make
関数は 3 つの引数を受け取ります:スライスタイプ、スライスの長さ、スライスの容量であり、スライスの容量はオプションの引数です。make
によって作成されたスライスは、基になる配列を参照する新しい配列をストレージに割り当てます。
make([]T, length, capacity)
make
の役割は、新しい配列を作成し、それをスライスすることです。したがって、次の 2 つの書き方は等価です:
make([]int, 50, 100)
new([100]int)[0:50]
配列と同様に、スライスは一般的に一次元ですが、多次元に組み合わせることもできます。配列内の配列はすべて同じ長さでなければなりませんが、スライス内のスライスの長さは動的に変化しますが、スライス内のスライスは個別に初期化する必要があります。
構造体型#
構造体は、名前付き要素のシーケンスであり、名前付き要素はフィールドとも呼ばれ、各フィールドは名前と型に対応します。フィールドの名前は明示的に指定することも(識別子リスト)、暗黙的に指定することも(埋め込みフィールド)できます。構造体内の非空フィールドは一意です。
StructType = "struct" "{" { FieldDecl ";" } "}" .
FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] .
EmbeddedField = [ "*" ] TypeName .
Tag = string_lit .
// 空の構造体
struct {}
// 6 つのフィールドを持つ構造体
struct {
x, y int
u float32
_ float32 // パディング
A *[]int
F func()
}
型が指定されているが名前が指定されていないフィールドは埋め込みフィールドと呼ばれ、埋め込みフィールドは型名 T または非インターフェース型のポインタ型 *T を指定する必要があります。ここで T はポインタ型であってはなりません。あるいは、非インターフェース型のポインタです。この場合、型名はフィールドの名前として使用されます。
// T1、*T2、P.T3、および *P.T4 の 4 つの埋め込みフィールドを持つ構造体
struct {
T1 // フィールド名は T1
*T2 // フィールド名は T2
P.T3 // フィールド名は T3
*P.T4 // フィールド名は T4
x, y int // フィールド名は x と y
}
以下の宣言はフィールド名が一意である必要があるため無効です。
struct {
T // 埋め込みフィールド *T と *P.T が衝突
*T // 埋め込みフィールド T と *P.T が衝突
*P.T // 埋め込みフィールド T と *T が衝突
}
x.f
がフィールドまたはメソッド f
を表す合法的なセレクタである場合、構造体 x
内の埋め込みフィールドのフィールドまたはメソッド f
が呼び出されます。
埋め込みフィールドから組み合わせたフィールドは、構造体の元のフィールドと基本的に同じ動作をしますが、構造体の複合リテラル内で直接使用することはできません。
与えられた構造体 S と型 T に基づいて、次のルールに従って組み合わせたメソッドセットを生成します:
- S に埋め込みフィールド T が含まれている場合、S および *S のメソッドセットには、受信者が T のメソッドセットが含まれ、*S には受信者が *T のメソッドセットが含まれます。
- S にフィールド *T が含まれている場合、S および *S には受信者が T および *T のすべてのメソッドセットが含まれます。
フィールドを宣言する際に、フィールドに文字列のタグを追加できます。このタグは、対応するフィールドの属性になります。空のタグとデフォルトのタグは同じです。タグの値はリフレクションインターフェースを介して取得でき、型構造体の型定義の一部として使用できますが、無視することもできます。
struct {
x, y float64 "" // 空のタグとデフォルトのタグは同じ
name string "any string is permitted as a tag"
_ [4]byte "ceci n'est pas un champ de structure"
}
// 構造体は TimeStamp のプロトコルバッファに対応します。
// タグ文字列はプロトコルバッファフィールドに対応する数字を定義します。
// 一般的に reflect パッケージを使用して読み取ります。
struct {
microsec uint64 `protobuf:"1"`
serverIP6 uint64 `protobuf:"2"`
}
ポインタ型#
ポインタ型は、指定された型の変数を指すポインタの集合を表します。この指定された型はポインタの基底型と呼ばれます。初期化されていないポインタの値は nil です。
PointerType = "*" BaseType .
BaseType = Type .
*Point
*[4]int
関数型#
関数型は、同じ引数型と戻り値型を持つすべての関数を表すことができます。初期化されていない関数型の値は nil です。
FunctionType = "func" Signature .
Signature = Parameters [ Result ] .
Result = Parameters | Type .
Parameters = "(" [ ParameterList [ "," ] ] ")" .
ParameterList = ParameterDecl { "," ParameterDecl } .
ParameterDecl = [ IdentifierList ] [ "..." ] Type .
引数と戻り値のリストでは、識別子リストは同時に存在するか省略される必要があります。存在する場合、各名前は指定された型の引数 / 戻り値を表し、これらの識別子は空であってはならず、重複してはなりません。省略された場合、指定された型の引数 / 戻り値は対応する型を使用して表されます。引数リストと戻り値リストは通常括弧を追加する必要がありますが、1 つの省略された戻り値がある場合は括弧を使用しなくても構いません。
関数の最後の引数には接頭辞 ...
を追加できます。このような引数を持つ関数は可変引数関数と呼ばれ、ゼロ個または複数の引数を受け取ることができます。
func()
func(x int) int
func(a, _ int, z float32) bool
func(a, b int, z float32) (bool)
func(prefix string, values ...int)
func(a, b int, z float64, opt ...interface{}) (success bool)
func(int, int, float64) (float64, *[]int)
func(n int) func(p *T)
インターフェース型#
インターフェース型は、メソッドセットを指定します。インターフェース型の変数は、そのインターフェースのスーパーセットである任意の型を保存できます。型がインターフェースを実装していると見なすことができます。初期化されていないインターフェース型の値は nil です。
InterfaceType = "interface" "{" { MethodSpec ";" } "}" .
MethodSpec = MethodName Signature | InterfaceTypeName .
MethodName = identifier .
InterfaceTypeName = TypeName .
インターフェース型のメソッドセットでは、各メソッドの名前は非空で一意でなければなりません。
// 簡単なファイルインターフェース
interface {
Read(b Buffer) bool
Write(b Buffer) bool
Close()
}
インターフェースは複数の型によって実装される可能性があります。たとえば、型 S1
と型 S2
の両方が次のメソッドセットを持っています:
func (p T) Read(b Buffer) bool { return … }
func (p T) Write(b Buffer) bool { return … }
func (p T) Close() { … }
(ここでの型 T は S1
または S2
を表すことができます) S1
と S2
はインターフェース File
を実装しており、型が他のメソッドを持っているかどうかは関係ありません。
型は、任意のメソッドセットのサブセットであるインターフェースを実装する可能性があります。したがって、複数の異なるインターフェースを実装する可能性があります。たとえば、すべての型は空のインターフェースを実装しています:
interface{}
同様に、次のインターフェース Locker
を考えてみてください:
type Locker interface {
Lock()
Unlock()
}
もし S1
と S2
がそれを実装している場合:
func (p T) Lock() { … }
func (p T) Unlock() { … }
それらはインターフェース Locker
と File
の両方を実装しています。
インターフェース T は、メソッドを指定するために別のインターフェース E を使用できます。この方法をインターフェース E をインターフェース T に埋め込むと呼びます。これにより、E 内のすべてのメソッド(エクスポートされたメソッドと未エクスポートのメソッドを含む)がインターフェース T に追加されます。
type ReadWriter interface {
Read(b Buffer) bool
Write(b Buffer) bool
}
type File interface {
ReadWriter // ReadWriter インターフェースのメソッドを追加するのと同じ
Locker // Locker インターフェースのメソッドを追加するのと同じ
Close()
}
type LockedFile interface {
Locker
File // 無効: Lock, Unlock は一意ではありません
Lock() // 無効: Lock は一意ではありません
}
インターフェース T は、自分自身またはすでに埋め込まれているインターフェースを再帰的に埋め込むことはできません。
// 無効: Bad は自分自身を埋め込むことはできません
type Bad interface {
Bad
}
// 無効: Bad1 はすでに参照されている Bad2 を埋め込むことはできません
type Bad1 interface {
Bad2
}
type Bad2 interface {
Bad1
}
マップ型#
map 型は、ユニークな値をキーとする無秩序な集合です。
MapType = "map" "[" KeyType "]" ElementType .
KeyType = Type .
map のキーの型は、比較演算子 ==
と !=
を使用して比較できる必要があります。したがって、キーの型は関数、map、またはスライスであってはなりません。キーがインターフェース型の場合、比較演算子はその動的値を比較できる必要があります。そうでない場合は、実行時エラーが発生します。
map[string]int
map[*T]struct{ x, y float64 }
map[string]interface{}
map 内の要素の個数は、その長さと呼ばれます。map m
の長さは、組み込み関数 len
を使用して取得でき、実行時に変更される可能性があります。map には、実行時に要素を追加したり取得したりでき、組み込み関数 delete
を使用して要素を削除できます。
新しい空の map を初期化するには、組み込み関数 make
を使用できます。これにより、map の型と予約されたスペースを指定できます:
make(map[string]int)
make(map[string]int, 100)
map の予約スペースは、map の長さを固定するものではありません。一定数の要素を追加することで長さを増やすことができます(nil map には要素を追加できません)。nil map と空の map は等しいですが、nil map には要素を追加できません。
チャネル型#
チャネルは、並行して実行される関数間で指定された型の値を送受信する手段を提供します。初期化されていないチャネルは nil です。
ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .
演算子 <-
は、チャネルのデータの流れの方向を指定できます。方向が指定されていない場合、チャネルはデフォルトで双方向です。チャネルは変換や代入を通じて、読み取り専用または書き込み専用に制限できます。
chan T // T 型のデータを受信および送信できます
chan<- float64 // float64 型の値のみを送信できます
<-chan int // int 型の値のみを受信できます
<-
は最左側の chan
に関連付けられます:
chan<- chan int // chan<- (chan int) と等価
chan<- <-chan int // chan<- (<-chan int) と等価
<-chan <-chan int // <-chan (<-chan int) と等価
chan (<-chan int)
チャネルを初期化するには、組み込みの make
関数を使用できます。make
関数は、チャネルの型と容量を指定できます。
make(chan int, 100)
容量は、最大でキャッシュできる要素の数を設定します。容量が設定されていないか、値が 0 の場合、チャネルはバッファなしになり、送信者と受信者の両方が準備が整ったときにのみデータが転送されます。バッファ付きのチャネルは、バッファが満杯でない限りデータを正常に送信でき、バッファが空でない場合はデータを正常に受信できます。値が nil のチャネルはデータを転送できません。
組み込み関数 close
を使用してチャネルを閉じることができます。受信側の 2 番目の戻り値は、閉じたチャネルにまだデータが含まれているかどうかを受信者に通知するために使用できます。
チャネルは送信文、受信操作で使用できます。複数の goroutine でチャネルの組み込み関数 len
と cap
を直接呼び出すことができ、同期性を考慮する必要はありません。チャネルの動作は FIFO キューと同じです。たとえば、ある goroutine がデータを送信し、別の goroutine がそれを受信する場合、受信データの順序は送信データの順序と同じです。
型の属性と値#
型識別子#
2 つの型は同じである場合もあれば異なる場合もあります。
定義された型はすべて異なる型です。2 つの型の基底型が構造的に同じであれば、それらは等しいと見なされます。一般的には:
-
2 つの配列の長さと要素型が同じであれば、それらは同じ型です。
-
2 つのスライスの要素型が同じであれば、それらは同じ型です。
-
2 つの構造体のフィールドの順序が同じであり、フィールド名、フィールド型、タグがすべて同じであれば、それらは等しいです。非エクスポートフィールドのフィールド名は異なるパッケージ内で常に異なります。
-
2 つのポインタの基底型が同じであれば、それらは同じ型です。
-
2 つの関数が同じ引数と戻り値のリストを持ち、型が同じであれば、それらは同じです。引数の名前は必ずしも同じである必要はありません。
-
2 つのインターフェースのメソッドセットが完全に同じであれば、それらは同じです。
-
2 つのマップ型のキー型と値型が同じであれば、それらは等しいです。
-
2 つのチャネル型が含むオブジェクト型とチャネルの方向が同じであれば、それらは同じです。
以下の宣言を考えてみましょう:
type (
A0 = []string
A1 = A0
A2 = struct{ a, b int }
A3 = int
A4 = func(A3, float64) *A0
A5 = func(x int, _ float64) *[]string
)
type (
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
)
type C0 = B0
これらの型は等しいです:
A0, A1, and []string
A2 and struct{ a, b int }
A3 and int
A4, func(int, float64) *[]string, and A5
B0, B0, and C0
[]int and []int
struct{ a, b *T5 } and struct{ a, b *T5 }
func(x int, y float64) *[]string, func(int, float64) (result *[]string), and A5
B0 と B1 は異なる型です。なぜなら、それらは型定義の方法でそれぞれ定義されているからです。func(int, float64) *B0
と func(x int, y float64) *[]string
は異なる型です。なぜなら、B0 と [] string は同じ型ではないからです。
割り当て可能性#
以下の条件を満たす場合、x を T 型の変数に割り当てることができます(x を T に割り当てる):
-
x の型が T である。
-
x の型 V と T の基底型が同じであり、型 T または V のいずれかが定義された型である。
-
T がインターフェース型であり、x が T を実装している。
-
x がチャネルであり、T がチャネル型であり、型 V と型 T の要素型が同じであり、2 つの型のいずれかが定義された型である。
-
x が nil であり、T がポインタ、関数、スライス、マップ、チャネル、またはインターフェース型である。
-
x が T 型の値を表す無型定数である。
代表性#
次の条件を満たす場合、T 型の値で定数 x を表すことができます:
-
T 値の集合に x が含まれている。
-
T が浮動小数点型であり、x がオーバーフローせずに T 型に近似できる。近似ルールは
IEEE 754 round-to-even
を使用します。負のゼロと符号なしのゼロは同じです。定数の値は負のゼロ、NaN、または無限大ではないことに注意してください。 -
T が複素数型であり、x の
real(x)
とimag(x)
部分が複素数型に対応する浮動小数点型(float32
またはfloat64
)で構成されている。
x T x は T の値を表すことができる、なぜなら:
'a' byte 97 は byte 型の値の集合に含まれる
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 に等しい
0i int 0 は整数値である
(42 + 0i) float32 42.0 (0 虚部) は float32 型の値の集合に含まれる
x T x は T の値を表すことができない、なぜなら:
0 bool 0 はブール値の集合に含まれない
'a' string 'a' は rune 型であり、文字列型の値の集合に含まれない
1024 byte 1024 は 8 ビット符号なし整数値の集合に含まれない
-1 uint16 -1 は 16 ビット符号なし整数値の集合に含まれない
1.1 int 1.1 は整数値ではない
42i float32 (0 + 42i) は float32 型の値の集合に含まれない
1e1000 float64 1e1000 は近似値を取るとオーバーフローする
コードブロック#
コードブロックは、大括弧で囲まれた宣言と文です。
Block = "{" StatementList "}" .
StatementList = { Statement ";" } .
ソースコード内に明示的なコードブロックがあるだけでなく、いくつかの暗黙のコードブロックもあります。
-
すべての Go コードを含むグローバルコードブロック。
-
すべてのパッケージのコードを含むパッケージコードブロック。
-
ファイル内のすべてのコードを含むファイルコードブロック。
-
各 if、switch、for の範囲は暗黙のブロックを形成します。
-
各 switch および select 条件には独自のコードブロックがあります。
コードブロックはネスト可能であり、スコープに影響を与えます。
宣言とスコープ#
宣言は、定数、型、変数、関数、ラベル、およびパッケージに識別子をバインドできます。プログラム内の各識別子は宣言する必要があります。同じ識別子を同じコードブロック内で 2 回宣言することはできません。また、同じ識別子をファイルとパッケージコードブロックの両方で同時に宣言することはできません。
空の識別子は、他の識別子と同様に宣言内で使用できます。ただし、空の識別子は識別子をバインドせず、宣言がないのと同じです。パッケージコードブロック内では、init
識別子は init
関数の識別子としてのみ使用でき、空の識別子と同様に、新しいバインディングを導入することはありません。
Declaration = ConstDecl | TypeDecl | VarDecl .
TopLevelDecl = Declaration | FunctionDecl | MethodDecl .
宣言された識別子のスコープは、宣言された識別子が存在するスコープです。
Go はブロックを使用して語彙の位置を規定します:
-
事前定義された識別子はグローバルスコープを持ちます。
-
すべての定義されたトップレベル識別子はパッケージスコープを持ちます。
-
インポートされたパッケージの名前識別子はファイルスコープを持ちます。
-
メソッドの受信者、関数の引数、戻り値の変数は関数スコープを持ちます。
-
関数内で定義されたパラメータと変数の識別子のスコープは、識別子が宣言されたブロックの終了までです。
コードブロック内で宣言された識別子は、その内部のコードブロック内で再宣言できます。内部コードブロックのスコープ内では、識別子は内部コードブロック内で宣言されたエンティティを表します。
パッケージ文は宣言に属しません。パッケージ名はどのスコープにも出現せず、同じパッケージに属する複数のファイルを識別し、インポート時にデフォルトのパッケージ名を指定するためにのみ使用されます。
ラベルのスコープ#
ラベルを宣言するためにラベル文を使用でき、break
、continue
、goto
構文で使用できます。ラベルが宣言されているが使用されていない場合は無効です。ラベルのスコープは、定義された関数体のみであり、早期再帰関数体にはスコープがありません。
空の識別子#
空の識別子はアンダースコア _
で表されます。一般的な非空識別子とは異なり、宣言、演算子、および代入文で特別な意味を持つ匿名識別子として機能します。
事前定義された識別子#
以下の識別子は、グローバルスコープで事前に宣言されています:
Types:
bool byte complex64 complex128 error float32 float64
int int8 int16 int32 int64 rune string
uint uint8 uint16 uint32 uint64 uintptr
Constants:
true false iota
Zero value:
nil
Functions:
append cap close complex copy delete imag len
make new panic print println real recover
エクスポートされた識別子#
識別子は、他のパッケージで使用するためにエクスポートできます。識別子がエクスポートされるのは、次の 2 つの条件が同時に満たされる場合です:
- 識別子の最初の文字が大文字(Unicode の
Lu
クラス)である。 - 識別子がパッケージスコープで宣言されているか、フィールド名 / メソッド名である。
他のすべての識別子はエクスポートされません。
識別子の一意性#
識別子の集合が与えられた場合、識別子が集合内の各識別子と異なる場合、その識別子は一意であると見なされます。2 つの識別子があると仮定します。スペルが異なる場合、または異なるパッケージ内でエクスポートされていない場合、それらは異なる識別子です。逆に、他の状況では識別子は同じであると見なされます。
定数宣言#
定数宣言は、定数式を使用して一連の識別子をバインドします。識別子の数は式の数と等しくなければなりません。左側の n 番目の識別子は、右側の n 番目の式の値をバインドします。
ConstDecl = "const" ( ConstSpec | "(" { ConstSpec ";" } ")" ) .
ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] .
IdentifierList = identifier { "," identifier } .
ExpressionList = Expression { "," Expression } .
型が指定されている場合、定数は型を指定し、式の値はその型に対して割り当て可能でなければなりません。
型が指定されていない場合、定数は対応する式の型に変換されます。式の値が無型定数である場合、宣言された定数も無型であり、定数の識別子は定数の値を表します。たとえば、小数部分が 0 であっても、式が浮動小数点リテラルである限り、定数識別子は浮動小数点数定数として表されます。
const Pi float64 = 3.14159265358979323846
const zero = 0.0 // 無型浮動小数点数定数
const (
size int64 = 1024
eof = -1 // 無型整数定数
)
const a, b, c = 3, 4, "foo" // a = 3, b = 4, c = "foo", 無型整数および文字列定数
const u, v float32 = 0, 3 // u = 0.0, v = 3.0
括弧内の定数宣言リストの式は、最初の式を除いて他の式を宣言する必要があります。空の式リストの値と型は、前の非空式と同じです。デフォルトの式リストは、以前の式を繰り返すことと等価です。識別子の数は、式の数と等しくなければなりません。iota
定数生成器は、連続した値のシーケンスを迅速に生成するためのメカニズムです。
const (
Sunday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Partyday
numberOfDays // 非エクスポート定数
)
Iota#
定数宣言内で、事前定義された識別子 iota
は連続した無型整数定数を表します。これは、定数宣言内の各定数定義の位置(ゼロから始まる)を表します。関連する定数の集合を生成するために使用できます:
const ( // iota は 0 にリセットされます
c0 = iota // c0 == 0
c1 = iota // c1 == 1
c2 = iota // c2 == 2
)
const ( // iota は 0 にリセットされます
a = 1 << iota // a == 1
b = 1 << iota // b == 2
c = 3 // c == 3 (iota を使用していませんが、値は依然として増加します)
d = 1 << iota // d == 8
)
const ( // iota は 0 にリセットされます
u = iota * 42 // u == 0 (無型整数定数)
v float64 = iota * 42 // v == 42.0 (float64 型定数)
w = iota * 42 // w == 84 (無型整数定数)
)
const x = iota // x == 0 (iota はリセットされます)
const y = iota // y == 0 (iota はリセットされます)
定義により、同じ定数定義内で iota
を複数回使用すると、同じ値が得られます:
const (
bit0, mask0 = 1 << iota, 1<<iota - 1 // bit0 == 1, mask0 == 0 (iota == 0)
bit1, mask1 // bit1 == 2, mask1 == 1 (iota == 1)
_, _ // (iota == 2, unused)
bit3, mask3 // bit3 == 8, mask3 == 7 (iota == 3)
)
最後の例では、最後の非空式リストの暗黙の繰り返しを利用しています。
型宣言#
型宣言は、型に識別子をバインドします。型宣言には 2 つの方法があります:型宣言とエイリアス宣言。
TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
TypeSpec = AliasDecl | TypeDef .
エイリアス宣言#
エイリアス宣言は、指定された型に識別子名をバインドします。
AliasDecl = identifier "=" Type .
識別子のスコープ内では、それは型のエイリアスとして機能します。
type (
nodeList = []*Node // nodeList と []*Node は同じ型
Polar = polar // Polar と polar は同じ型を表します
)
型定義#
型定義は、新しい型を作成し、識別子をバインドします。新しい型は、指定された型と同じ基底型と操作を持ちます。
TypeDef = identifier Type .
この型は定義型と呼ばれ、他のすべての型とは異なります。作成した型とも異なります。
type (
Point struct{ x, y float64 } // Point と struct{ x, y float64 } は異なる型
polar Point // polar と Point は異なる型
)
type TreeNode struct {
left, right *TreeNode
value *Comparable
}
type Block interface {
BlockSize() int
Encrypt(src, dst []byte)
Decrypt(src, dst []byte)
}
定義型は、その型に関連するメソッドを定義できます。元の型のメソッドは継承されません。ただし、インターフェース