構造体とスライスを使用したGoでよく見かけるパターンを紹介

Go言語
この記事は約7分で読めます。
Go初学者
Go初学者

構造体を要素にしたスライスって、どうやって定義するのかな?

この記事では構造体とスライスについて理解できます!
  • 構造体を要素にしたスライスの基本的な定義方法
  • make() 関数を使用した定義方法
  • 参照渡しで構造体を要素にしたスライスの定義方法

今回は構造体を要素にしたスライスの定義方法をご紹介いたします。

WEBアプリ開発でJSON形式のデータを扱う時に、Goではよく見かけるパターンですので押さえておきましょう!

もりぴ
この記事を書いた人

XHTML1.0時代にHTML&CSSを勉強した経験あり。無趣味だった私が2020年5月からプログラミング学習を開始し現在も挫折せずに趣味で学習を楽しんでいる51歳。プログラミングの楽しさをブログを通してお伝えしていきます。

もりぴをフォローする

構造体を要素にしたスライスの基本的な定義方法(値渡し)

それでは、値渡しによる基本的な構造体を要素にしたスライスの定義方法を、簡単なプログラムで確認していきます。

fmt.Println()でスライスを出力する

// 構造体を要素にしたスライスの基本的な定義方法(値渡し)
package main

import "fmt"

type Player struct {
    Name  string
    Level int
}

// Player型を元にスライスを格納できる型を作る(値渡し)
type Players []Player

func main() {
    // Players型検証用にPlayerをいくつか初期化する
    player1 := Player{Name: "morip", Level: 10}
    player2 := Player{Name: "PHP", Level: 5}
    player3 := Player{Name: "Golang", Level: 8}

    // Players型の変数を宣言する
    players := Players{}

    // 変数に構造体のデータをスライスに代入する
    players = append(players, player1, player2, player3)

    // 値を出力
    fmt.Println(players)
}
// 出力結果
$ go run main.go
[{morip 10} {PHP 5} {Golang 8}]

スライスに構造体のデータが代入されているのが確認できます。

for文で構造体の値を出力する

次にfor文で、構造体の値を出力してみましょう。

// 構造体を要素にしたスライスの基本的な定義方法(値渡し)
package main

import "fmt"

type Player struct {
    Name  string
    Level int
}

// Player型を元にスライスを格納できる型を作る(値渡し)
type Players []Player

func main() {
    // Players型検証用にPlayerをいくつか初期化する
    player1 := Player{Name: "morip", Level: 10}
    player2 := Player{Name: "PHP", Level: 5}
    player3 := Player{Name: "Golang", Level: 8}

    // Players型の変数を宣言する
    players := Players{}

    // 変数に構造体のデータをスライスに代入する
    players = append(players, player1, player2, player3)

    // for文を使用して値を出力
    for i, v := range players {
	fmt.Println(i, v)
    }
    // インデックス番号が不要な場合
    for _, v := range players {
	fmt.Println(v)
    }
}
// 出力結果
$ go run main.go
0 {morip 10}  // インデックス番号あり
1 {PHP 5}
2 {Golang 8}
{morip 10}  // インデックス番号なし
{PHP 5}
{Golang 8}

通常のスライス同様に、for文でも値が出力できることが確認できました。

make()関数を使用した定義方法

構造体を要素に持つスライスでも、通常のスライスと同様に make() 関数でメモリ領域を確保してから値を代入することができます。

// 構造体を要素にしたスライスの基本的な定義方法(値渡し)
package main

import "fmt"

type Player struct {
    Name  string
    Level int
}

// Player型を元にスライスを格納できる型を作る(値渡し)
type Players []Player

func main() {
    // Players型検証用にPlayerをいくつか初期化する
    player1 := Player{Name: "morip", Level: 10}
    player2 := Player{Name: "PHP", Level: 5}
    player3 := Player{Name: "Golang", Level: 8}

    // make()関数を使う
    players2 := make(Players, 0)

    players2 = append(players2, player1, player2, player3)

    // 値を出力
    fmt.Println(players2)

    // for文を使用して値を出力
    for _, v := range players2 {
	fmt.Println(v)
    }
}
// 出力結果
$ go run main.go
[{morip 10} {PHP 5} {Golang 8}]
{morip 10}
{PHP 5}
{Golang 8}

参照渡しで構造体を要素としてスライスを定義

構造体のデータが大きくて値渡しではコピーによりメモリが圧迫される時や、関数を利用して構造体の値を変更したい時などは参照渡しを利用します。

ポインタの基本を理解していれば大丈夫でしょう。

それでは、プログラムで確認していきます。

// 参照渡しで構造体を要素としてスライスを定義
package main

import "fmt"

type Player struct {
    Name  string
    Level int
}

// Player型を元にスライスを格納できる型を作る(参照渡し)
type PointerPlayers []*Player

func main() {
    // Players型検証用にPlayerをいくつか初期化する
    player1 := Player{Name: "morip", Level: 10}
    player2 := Player{Name: "PHP", Level: 5}
    player3 := Player{Name: "Golang", Level: 8}

    // PointerPlayers型の変数を宣言(ポインタで)
    players3 := PointerPlayers{}

    // PointerPlayers型はポインタなので&を付ける
    players3 = append(players3, &player1, &player2, &player3)

    // ポインタなので出力結果はアドレス
    fmt.Println(players3)

    // 実体を出力
    for _, v := range players3 {
        fmt.Println(*v)
    }

    players4 := make(PointerPlayers, 0)
    players4 = append(players4, &player1, &player2, &player3)

    // ポインタであるこを確認
    fmt.Println(players4)

    // 実体を出力
    for _, v := range players4 {
        fmt.Println(*v)
    }
}
// 出力結果
$ go run main.go
[0xc00000c030 0xc00000c048 0xc00000c060]
{morip 10}
{PHP 5}
{Golang 8}
[0xc00000c030 0xc00000c048 0xc00000c060]  // make()による出力
{morip 10}
{PHP 5}
{Golang 8}

値渡しと参照渡しのどちらで定義するかは、あなたが開発してるアプリの状況に応じて選択していきましょう。

【最後に】構造体を要素に持つスライスの定義方法

今回は、構造体を要素に持つスライスの定義方法をお伝えしてきました。

スライス定義の基本をしっかり押さえておけば、そんなに難しい内容ではなかったと思います。

私もGoでは経験無いのですが、WEB APIを扱う時などに覚えておいて損はないパターンですので覚えておきましょう。

comment

タイトルとURLをコピーしました