序章

具体的な詳細を中心に抽象化を構築することは、プログラミング言語が開発者に提供できる最高のツールです。 構造体を使用すると、Go開発者はGoプログラムが動作する世界を説明できます。 を説明する文字列について推論する代わりに Street, City、または PostalCode、構造体を使用すると、代わりに Address. これらは、将来の開発者(私たち自身を含む)にGoプログラムにとって重要なデータと、将来のコードがそのデータを適切に使用する方法を伝える取り組みにおいて、ドキュメントの自然なつながりとして機能します。 構造体は、いくつかの異なる方法で定義および使用できます。 このチュートリアルでは、これらの各テクニックを見ていきます。

構造体の定義

構造体は、たとえば税金を申告するために使用する紙のフォームのように機能します。 紙のフォームには、名前や名前などのテキスト情報のフィールドがある場合があります。 テキストフィールドに加えて、フォームには、「既婚」や「単一」などのブール値、または生年月日の日付フィールドを示すチェックボックスがある場合があります。 同様に、構造体はさまざまなデータをまとめて収集し、さまざまなフィールド名で整理します。 新しい構造体で変数を初期化すると、フォームをコピーして入力できるようにしたかのようになります。

新しい構造体を作成するには、最初に、構造体に含まれるフィールドを説明する青写真をGoに与える必要があります。 この構造体の定義は通常、キーワードで始まります type 構造体の名前が続きます。 この後、 struct キーワードの後に中括弧のペアが続く {} 構造体に含まれるフィールドを宣言します。 構造体を定義すると、この構造体定義を使用する変数を宣言できるようになります。 この例では、構造体を定義して使用します。

package main

import "fmt"

type Creature struct {
	Name string
}

func main() {
	c := Creature{
		Name: "Sammy the Shark",
	}
	fmt.Println(c.Name)
}

このコードを実行すると、次の出力が表示されます。

output
Sammy the Shark

まず、 Creature この例の構造体には、 Name タイプのフィールド string. の体内 main、のインスタンスを作成します Creature タイプの名前の後に中括弧のペアを配置することにより、 Creature、次にそのインスタンスのフィールドの値を指定します。 のインスタンス c その Name フィールドは「SammytheShark」に設定されています。 以内 fmt.Println 関数の呼び出しでは、インスタンスが作成された変数の後にピリオドを置き、その後にアクセスするフィールドの名前を付けることで、インスタンスのフィールドの値を取得します。 例えば、 c.Name この場合、 Name 分野。

構造体の新しいインスタンスを宣言するときは、通常、最後の例のように、フィールド名とその値を列挙します。 または、構造体のインスタンス化中にすべてのフィールド値が提供される場合は、次の例のようにフィールド名を省略できます。

package main

import "fmt"

type Creature struct {
	Name string
	Type string
}

func main() {
	c := Creature{"Sammy", "Shark"}
	fmt.Println(c.Name, "the", c.Type)
}

出力は最後の例と同じです。

output
Sammy the Shark

にフィールドを追加しました Creature 追跡するには Type としての生き物の string. インスタンス化する場合 Creature の体内で main、各フィールドの値を順番に指定し、フィールド名を省略することで、より短いインスタンス化形式を使用することを選択しました。 宣言で Creature{"Sammy", "Shark"}Name フィールドは値を取ります Sammy そしてその Type フィールドは値を取ります Shark なぜなら Name タイプ宣言の最初に表示され、次に表示されます Type.

この短い宣言フォームにはいくつかの欠点があり、ほとんどの状況でGoコミュニティは長いフォームを好むようになりました。 短い宣言を使用するときは、構造体の各フィールドに値を指定する必要があります。気にしないフィールドをスキップすることはできません。 これにより、多くのフィールドを持つ構造体の短い宣言がすぐに混乱します。 このため、短い形式を使用して構造体を宣言することは、通常、フィールドが少ない構造体で使用されます。

これまでの例のフィールド名はすべて大文字で始まっています。 これは、文体の好みよりも重要です。 フィールド名に大文字または小文字を使用すると、他のパッケージで実行されているコードがフィールド名にアクセスできるかどうかに影響します。

構造体フィールドのエクスポート

構造体のフィールドは、Goプログラミング言語内の他の識別子と同じエクスポートルールに従います。 フィールド名が大文字で始まる場合、構造体が定義されたパッケージの外部のコードで読み取りおよび書き込みが可能です。 フィールドが小文字で始まる場合、その構造体のパッケージ内のコードのみがそのフィールドの読み取りと書き込みを行うことができます。 この例では、エクスポートされるフィールドとエクスポートされないフィールドを定義します。

package main

import "fmt"

type Creature struct {
	Name string
	Type string

	password string
}

func main() {
	c := Creature{
		Name: "Sammy",
		Type: "Shark",

		password: "secret",
	}
	fmt.Println(c.Name, "the", c.Type)
	fmt.Println("Password is", c.password)
}

これは出力します:

output
Sammy the Shark Password is secret

前の例にフィールドを追加しました。 secret. secret 未輸出です string フィールド。これは、インスタンス化を試みる他のパッケージを意味します。 Creature アクセスまたは設定することはできません secret 分野。 この例のように、同じパッケージ内でこれらのフィールドにアクセスできます。 以来 main にもあります main パッケージ、それは参照することができます c.password そこに保存されている値を取得します。 構造体にエクスポートされていないフィールドがあり、それらにアクセスできるのは、エクスポートされたメソッドによって仲介されるのが一般的です。

インライン構造

構造体を表す新しいタイプを定義することに加えて、インライン構造体を定義することもできます。 これらのオンザフライの構造体定義は、構造体タイプの新しい名前を作成するのに無駄な労力がかかる状況で役立ちます。 たとえば、テストでは多くの場合、構造体を使用して、特定のテストケースを構成するすべてのパラメーターを定義します。 次のような新しい名前を思い付くのは面倒です CreatureNamePrintingTestCase その構造体が1か所でのみ使用されている場合。

インライン構造体の定義は、変数割り当ての右側に表示されます。 定義する各フィールドの値を含む中括弧のペアを追加して、直後にそれらのインスタンス化を提供する必要があります。 次の例は、インライン構造体の定義を示しています。

package main

import "fmt"

func main() {
	c := struct {
		Name string
		Type string
	}{
		Name: "Sammy",
		Type: "Shark",
	}
	fmt.Println(c.Name, "the", c.Type)
}

この例の出力は次のようになります。

output
Sammy the Shark

構造体を記述する新しいタイプを定義するのではなく、 type キーワード、この例では、を配置することによってインライン構造体を定義します struct 短い代入演算子の直後の定義、 :=. 前の例のように構造体のフィールドを定義しますが、すぐに別のブレースのペアと各フィールドが想定する値を指定する必要があります。 この構造体の使用は以前とまったく同じになりました。ドット表記を使用してフィールド名を参照できます。 インライン構造体が宣言される最も一般的な場所はテスト中です。これは、特定のテストケースのデータと期待値を含むように1回限りの構造体が定義されることが多いためです。

結論

構造体は、情報を整理するためにプログラマーによって定義された異種データのコレクションです。 ほとんどのプログラムは膨大な量のデータを処理し、構造体がないと、どれを覚えるのが難しくなります。 string また int 変数は一緒に属しているか、または異なっていました。 次回、変数のグループをジャグリングしていることに気付いたときは、これらの変数を使用してグループ化する方がよいかどうかを自問してください。 struct. これらの変数は、ずっと高レベルの概念を説明していた可能性があります。