演習 - 配列を使用する

完了

Go の配列は、特定の型の固定長のデータ構造です。 0 個以上の要素を保持することができ、それらを宣言または初期化するときにサイズを定義する必要があります。 また、"作成後にサイズを変更することはできません"。 これらの理由により、配列は Go プログラムでは一般に使用されませんが、スライスとマップの基盤となっています。

配列を宣言する

Go で配列を宣言するには、その要素のデータ型と、配列が保持できる要素の数を定義する必要があります。 配列内の各要素には、添字表記を使用してアクセスできます。ここで、最初の要素は 0 で、最後の要素は配列の長さよりも 1 小さい値になります (長さ - 1)。

たとえば、次のコードを使用してみましょう。

package main

import "fmt"

func main() {
    var a [3]int
    a[1] = 10
    fmt.Println(a[0])
    fmt.Println(a[1])
    fmt.Println(a[len(a)-1])
}

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

0
10
0

配列を宣言したのですが、その要素にアクセスしてもエラーが発生しません。 既定では、各要素が既定のデータ型で初期化されます。 この場合、int の既定値は 0 です。 ただし、a[1] = 10 で行ったように、特定の位置に値を割り当てることができます。 同じ表記法を使用して、その要素にアクセスすることができます。 また、最初の要素を参照するために、a[0] を使ったことに注意してください。 最後の要素を参照するには、a[len(a)-1] を使いました。 len 関数は、配列、スライス、またはマップの要素数を取得するための Go の組み込み関数です。

配列を初期化する

配列を宣言するときに、既定値以外の値を使用して配列を初期化することもできます。 たとえば、次のコードを使用してその構文を確認してテストすることができます。

package main

import "fmt"

func main() {
    cities := [5]string{"New York", "Paris", "Berlin", "Madrid"}
    fmt.Println("Cities:", cities)
}

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

Cities: [New York Paris Berlin Madrid ]

この配列には 5 つの要素がありますが、すべての要素に値を割り当てる必要はありません。 前に見たように、最後の位置は空の文字列であり、これは文字列データ型の既定値です。

配列での省略記号

必要な位置の数はわからなくても、データ要素のセットはわかっている場合に、配列を宣言して初期化するもう 1 つの方法は、次の例のように省略記号 (...) を使う方法です。

q := [...]int{1, 2, 3}

省略記号を使用するように、前のセクションで使用したプログラムを変更してみましょう。 コードは次の例のようになります。

package main

import "fmt"

func main() {
    cities := [...]string{"New York", "Paris", "Berlin", "Madrid"}
    fmt.Println("Cities:", cities)
}

上記のコードを実行すると、次の例のような出力が表示されます。

Cities: [New York Paris Berlin Madrid]

違いがわかりましたか。 末尾に空の文字列がありません。 配列の長さは、初期化時に指定した文字列によって決まります。 必要になるかどうかわからないメモリは予約されません。

配列を初期化するためのもう 1 つの興味深い方法は、省略記号を使用して、最後の位置の値のみを指定する方法です。 たとえば、次のコードを使用します。

package main

import "fmt"

func main() {
    numbers := [...]int{99: -1}
    fmt.Println("First Position:", numbers[0])
    fmt.Println("Last Position:", numbers[99])
    fmt.Println("Length:", len(numbers))
}

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

First Position: 0
Last Position: -1
Length: 100

99 番目の位置の値を指定したため、配列の長さが 100 になったことに注目してください。 最初の位置には、既定値 (ゼロ) が出力されています。

多次元配列

Go では、複合データ構造を使用する必要がある場合に、多次元配列がサポートされます。 2 次元配列を宣言して初期化するプログラムを作成してみましょう。 次のコードを使用します。

package main

import "fmt"

func main() {
    var twoD [3][5]int
    for i := 0; i < 3; i++ {
        for j := 0; j < 5; j++ {
            twoD[i][j] = (i + 1) * (j + 1)
        }
        fmt.Println("Row", i, twoD[i])
    }
    fmt.Println("\nAll at once:", twoD)
}

上記のプログラムを実行すると、次の例のような出力が表示されます。

Row 0 [1 2 3 4 5]
Row 1 [2 4 6 8 10]
Row 2 [3 6 9 12 15]

All at once: [[1 2 3 4 5] [2 4 6 8 10] [3 6 9 12 15]]

この var twoD [3][5]int のように配列の 2 番目の次元に保持する位置の数を指定した 2 次元配列を宣言しました。 この配列は、スプレッドシートやマトリックスなどのように列と行を持つ 1 つのデータ構造と考えることができます。 この時点では、すべての位置に既定値 0 が設定されています。 for ループでは、すべての位置を初期化して、すべての行が異なる値パターンとなるようにしました。 最後に、すべての値をターミナルに出力しています。

3 次元配列を宣言するにはどうすればよいでしょうか。 どのような構文であるか思い付いていることでしょう。 これは次の例のように記述することができます。

package main

import "fmt"

func main() {
    var threeD [3][5][2]int
    for i := 0; i < 3; i++ {
        for j := 0; j < 5; j++ {
            for k := 0; k < 2; k++ {
                threeD[i][j][k] = (i + 1) * (j + 1) * (k + 1)
            }
        }
    }
    fmt.Println("\nAll at once:", threeD)
}

上記のコードを実行すると、次の例のような出力が表示されます。

All at once: [[[1 2] [2 4] [3 6] [4 8] [5 10]] [[2 4] [4 8] [6 12] [8 16] [10 20]] [[3 6] [6 12] [9 18] [12 24] [15 30]]]

この出力をより読みやすい形式で書式設定すると、次の例のようになります。

All at once: 
[
    [
        [1 2] [2 4] [3 6] [4 8] [5 10]
    ] 
    [
        [2 4] [4 8] [6 12] [8 16] [10 20]
    ] 
    [
        [3 6] [6 12] [9 18] [12 24] [15 30]
    ]
]

構造体が 2 次元配列からどのように変わったかに注目してください。 必要に応じてさらに多くの次元を作成できますが、別のデータ型の説明に進むため、ここまでにしておきます。