第8章 配列

配列

Go言語における「配列」は、同じ型の要素を一定の数だけ格納するためのデータ構造です。配列の長さは固定で、宣言時に決定されます。以下にGo言語での配列の使用例をいくつか示します。


配列の宣言

配列は、要素の型と括弧内の要素数で宣言されます。

var a [5]int // int型の要素を5つ持つ配列
fmt.Println(a) // 初期値では全要素がゼロ値(この場合は0)で初期化される


配列の初期化

配列はリテラルを使用して初期化することができます。

b := [5]int{1, 2, 3, 4, 5} // 初期値を持つ配列
fmt.Println(b) // 出力: [1 2 3 4 5]


配列へのアクセスと代入

配列の特定の要素にアクセスするには、インデックスを使用します。インデックスは0から始まります。

var c [5]int
c[0] = 100
c[1] = 200
fmt.Println(c) // 出力: [100 200 0 0 0]

// 特定の要素にアクセス
fmt.Println(c[0]) // 出力: 100


配列の長さ

配列の長さは、len関数を使って取得できます。

fmt.Println(len(c)) // 出力: 5


配列の繰り返し処理

配列の要素に対する繰り返し処理は、forループを使って行います。

for i := 0; i < len(c); i++ {
    fmt.Println(c[i])
}

// インデックスと値の両方が必要な場合はrangeを使用
for i, v := range c {
    fmt.Println("インデックス:", i, "値:", v)
}


配列のコピー

Go言語では、配列を別の配列に代入すると、配列の内容がコピーされます。つまり、一方の配列の要素を変更しても、他方の配列には影響しません。

a := [3]int{1, 2, 3}
b := a // aの内容がbにコピーされる
b[0] = 100
fmt.Println(a) // 出力: [1 2 3]
fmt.Println(b) // 出力: [100 2 3]


配列リテラルの省略形

配列リテラルでは、要素数を省略して...を使用することができます。これにより、配列の長さは初期化時の要素数によって自動的に決定されます。

c := [...]int{4, 5, 6}
fmt.Println(c)      // 出力: [4 5 6]
fmt.Println(len(c)) // 出力: 3


多次元配列

Go言語では、多次元配列もサポートされています。例えば、2次元配列を定義することができます。

var d [2][3]int
d[0][0] = 1
d[0][1] = 2
d[0][2] = 3
d[1][0] = 4
d[1][1] = 5
d[1][2] = 6
fmt.Println(d) // 出力: [[1 2 3] [4 5 6]]


配列とスライスの違い

配列と似ているがより柔軟なスライス(slice)もGo言語には存在します。スライスは配列に基づいており、動的なサイズ変更や部分的な配列の参照が可能です。

e := []int{7, 8, 9} // スライス
fmt.Println(e)      // 出力: [7 8 9]


スライス

Go言語における「スライス」は、配列よりも柔軟で動的なデータ構造です。スライスは配列の上に構築され、サイズが固定されていないため、ランタイム中にサイズが変更できます。以下にスライスの使用例を示します。


スライスの基本

スライスは[]Tの形式で宣言され、Tはスライスの要素の型を示します。

// スライスの作成と初期化
s := []int{1, 2, 3}
fmt.Println(s) // 出力: [1 2 3]

// make関数によるスライスの作成
s := make([]int, 3) // 長さ3のint型のスライス
fmt.Println(s) // 出力: [0 0 0]


スライスへのアクセスと変更

スライスの要素にアクセスや変更は、配列と同様にインデックスを使用して行います。

s[0] = 100
fmt.Println(s) // 出力: [100 0 0]


スライスの追加と拡張

append関数を使って、スライスに新しい要素を追加できます。この操作は、必要に応じてスライスの容量を自動的に拡張します。

s = append(s, 4, 5)
fmt.Println(s) // 出力: [100 0 0 4 5]


スライスの長さと容量

スライスの長さと容量は、len(s)cap(s)で取得できます。長さはスライスに含まれる要素の数を、容量はスライスの下にある配列のサイズを表します。

fmt.Println("長さ:", len(s)) // 出力: 長さ: 5
fmt.Println("容量:", cap(s)) // 出力: 容量: 6 (またはそれ以上)


スライスのスライス化

スライスは、[開始インデックス:終了インデックス]の形式で、既存のスライスから新しいスライスを作成することができます。

t := s[1:3]
fmt.Println(t) // 出力: [0 0]


マップ

Go言語における「マップ」は、キーと値のペアを格納する連想配列(または辞書)のデータ構造です。マップはキーを使用して効率的にデータを格納、検索、更新できます。以下にマップの使用例を示します。


マップの作成と初期化

マップはmap[KeyType]ValueTypeの形式で宣言されます。KeyTypeはマップのキーとなる型で、ValueTypeはマップの値の型です。

// 空のマップを作成
var m map[string]int
m = make(map[string]int)

または、リテラルを使用して初期化できます。

m := map[string]int{"apple": 5, "banana": 2}


マップへのアクセスと変更

マップに値を追加するには、キーを指定して値を代入します。

m["orange"] = 4
fmt.Println(m) // 出力: map[apple:5 banana:2 orange:4]

マップから値を取得するには、キーを指定します。

fmt.Println(m["apple"]) // 出力: 5

キーが存在するかどうかは、2つ目の戻り値で確認できます。

value, ok := m["apple"]
if ok {
    fmt.Println("apple の値:", value)
} else {
    fmt.Println("apple は存在しない")
}


マップからの要素の削除

delete関数を使用してマップから要素を削除できます。

delete(m, "banana")
fmt.Println(m) // 出力: map[apple:5 orange:4]


マップの繰り返し処理

forループとrangeを使用して、マップのすべてのキーと値を繰り返し処理できます。

for key, value := range m {
    fmt.Println("キー:", key, "値:", value)
}


練習問題1.

整数型の要素を5つ持つ配列aを作成し、それぞれの要素に1から5までの数値を割り当ててください。その後、配列のすべての要素を出力してください。

package main

import "fmt"

func main() {
    // 配列の作成と初期化
    var a [5]int
    // ここにコードを追加

    // 配列の要素を出力
    // ここにコードを追加
}


練習問題2.

整数型の要素を5つ持つ配列bが与えられたとき、配列のすべての要素の合計を計算し、出力してください。

package main

import "fmt"

func main() {
    b := [5]int{1, 2, 3, 4, 5}
    // ここにコードを追加
}


練習問題3.

整数型の要素を5つ持つ配列cを作成し、それを逆順にした新しい配列dを作成してください。その後、配列dのすべての要素を出力してください。

package main

import "fmt"

func main() {
    c := [5]int{1, 2, 3, 4, 5}
    var d [5]int
    // ここにコードを追加

    // 配列 d の要素を出力
    // ここにコードを追加
}