Goでの構造体の定義

提供:Dev Guides
移動先:案内検索

序章

具体的な詳細を中心に抽象化を構築することは、プログラミング言語が開発者に提供できる最高のツールです。 構造体を使用すると、Go開発者はGoプログラムが動作する世界を説明できます。 StreetCity、または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)
}

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

outputSammy the Shark

この例では、最初にCreature構造体を定義します。この構造体には、stringタイプのNameフィールドが含まれています。 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)
}

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

outputSammy the Shark

Creatureにフィールドを追加して、クリーチャーのTypestringとして追跡します。 mainの本体内でCreatureをインスタンス化する場合、各フィールドの値を順番に指定し、フィールド名を省略して、より短いインスタンス化形式を使用することを選択しました。 宣言Creature{"Sammy", "Shark"}では、Nameフィールドは値Sammyを取り、Typeフィールドは値Sharkを取ります。これは[ X139X]は型宣言の最初に表示され、次に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)
}

これは出力します:

outputSammy the Shark
Password is secret

前の例にsecretというフィールドを追加しました。 secretはエクスポートされていないstringフィールドです。つまり、Creatureをインスタンス化しようとする他のパッケージは、そのsecretフィールドにアクセスまたは設定できません。 。 この例のように、同じパッケージ内でこれらのフィールドにアクセスできます。 mainmainパッケージに含まれているため、c.passwordを参照して、そこに格納されている値を取得できます。 構造体にエクスポートされていないフィールドがあり、それらにアクセスできるのは、エクスポートされたメソッドによって仲介されるのが一般的です。

インライン構造

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

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

package main

import "fmt"

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

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

outputSammy the Shark

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

結論

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