基本文法一覧

【Go入門】配列型(要素数までを定義に含める静的配列)

こんにちは。Go入門ブログの第8回です。
本記事では、Goにおける配列型について解説します。

以下の記事において、数値型や文字列型といったGoの基本型について解説しました。

【Go入門】基本型と数値型変換(キャスト)・文字列リテラル

配列型は、これらの基本型の応用といえます。
Goの配列型は、他のプログラミング言語のそれとはやや異なる特徴を持っています。
最初は面くらうかもしれませんが、しっかり理解していきましょう。

配列型の定義

配列定義の書式

配列型は、以下の書式で定義できます。

[要素数]型の種類

たとえば、[2]intは2つの要素を持つ数値型の配列です。
同様に、[10]stringは10個の要素を持つ文字列型の配列になります。

要素の初期値を指定する

配列の宣言時に各要素の初期値を指定することができます。
要素数と型の指定の後に、{ }で囲ったブロックにカンマ区切りで要素の値を記述します。

[要素数]型の種類{要素1の初期値,要素2の初期値…}

なお、初期値を指定する場合、すべての要素の初期値を記述する必要はありません。
配列型の要素数よりも少ない数の初期値を指定した場合、残りの要素には型に応じたゼロ値が与えられます。
以下の例をみてください。

package main

import (
    "fmt"
)

func main() {
    // 要素数6の数値型配列に4つの初期値を指定する
    evens := [6]int{2, 4, 6, 8}
    // 配列の内容を出力
    fmt.Println(evens)
}

このサンプルの実行結果は以下のようになります。

$ go run main.go
[2 4 6 8 0 0]

要素数6の配列に4つだけ初期値を指定しているので、初期値が指定されていない5つめと6つめの要素は0になっています。
配列が文字列かたの場合は””(空文字列)、bool型の場合はfalseになります。

要素数の記述を省略する

配列の要素に初期値を与える場合、配列定義の要素数に...を記述することで要素数を省略することができます。

package main

import (
    "fmt"
)

func main() {
    // 要素数の定義を省略
    evens := [...]int{2, 4, 6, 8}
    // 配列の内容を出力
    fmt.Println(evens)
}

このサンプルの実行結果は以下のようになります。

$ go run main.go
[2 4 6 8]

先ほどとは違い、与えた初期値だけが出力されています。
要素数の指定を省略したので、与えた初期値の数がそのまま配列型の要素数になっているためです。

配列型の値の参照と代入

要素の参照と代入

配列型変数の指定した要素の値を取得したい場合、配列型変数名[要素番号]の形式で要素を参照できます。
要素に値を代入する場合も、配列型変数名[要素番号] = 値の形式で記述できます。

また、要素のインデックスは0から始まります。
たとえば要素数が5つの場合、インデックスは0、1、2、3、4となります。

package main

import (
    "fmt"
)

func main() {
    // 要素数4の数値型配列を定義
    var evens [4]int
    
    // 各要素に値を代入
    evens[0] = 2;
    evens[1] = 4;
    evens[2] = 6;
    evens[3] = 8;
    
    // 配列の要素をひとつずつ出力
    fmt.Println(evens[0],evens[1],evens[2],evens[3])
}

このサンプルの実行結果は以下のようになります。

$ go run main.go
2 4 6 8
配列型同士の代入

Goの配列型は、要素の数まで含めて定義されます。
したがって、配列型の変数に配列を代入する場合、型と要素数の両方が一致している必要があります。
型の種類が同じでも、要素数が一致しない場合はエラーになります。

package main

func main() {
    // 要素数3と4の数値型配列を定義
    var array1 [3]int
    evens := [4]int{2,4,6,8}
    
    // 配列を代入
    array1 = evens 
}

このサンプルの実行結果は以下のようになります。

$ go run main.go
# command-line-arguments
.\main.go:9:9: cannot use evens (type [4]int) as type [3]int in assignment

エラーメッセージに出力を見ると、[4]intという型を[3]intという型に代入しようとしてエラーになっていることがわかります。

以下のように、要素の数まで同じにすれば配列同士の代入が可能です。

package main

import (
    "fmt"
)

func main() {
    // 要素数4の数値型配列を2つ定義
    var array1 [4]int
    evens := [4]int{2, 4, 6, 8}

    // 配列を代入
    array1 = evens

    // 出力
    fmt.Println(array1)
}

実行すると、array1にきちんとevensの値が代入されていることがわかります。

$ go run main.go
[2 4 6 8]

要素数の変更

他の多くの言語では、動的配列(可変長配列)を使用可能です。
要素数を決めずに配列型を定義したり、後から要素を追加・削除したりできます。

しかしGoでは、ここまで説明してきたように、配列型は[n]T型の書式で要素数までを含めて厳密に定義します。
したがってGoの配列は、定義後に要素数の変更をおこなえない静的配列であるといえます。

それでは、Goでは動的配列を扱えないかというと、勿論そんなことはありません。
Goではスライスというデータ構造が、他言語での動的配列に該当する機能を提供します。

スライスは配列型と類似した特長を多く持ちますが、参照型のデータであり明確に別物です。
スライスについては今後の記事で詳しく解説しますが、配列型との違いをきちんと理解するためにも本記事の内容をしっかりと理解してください。

終わりに

本記事で、Goにおける配列型が他言語とは異なる特徴を持つことをお分かりいただけたかと思います。
最後にもう一度おさらいしておきましょう。

  • Goの配列型は要素数も含めて厳密に定義される
  • 要素の型が同じであっても、要素数の異なる配列同士は互換性を持たない
  • 配列型は要素数を指定せずに定義したり、後から要素を増減させることはできない
  • いわゆる可変長配列を扱いたい場合、配列型ではなくスライスという参照型を使用する

今回までの記事で、変数や型といったGoの基本的なコンポーネントについて概ね理解できたかと思います。
次回の記事では、条件分岐やループといった基本的な制御文について解説します。


スポンサーリンク
スポンサーリンク
スポンサーリンク