チュートリアル

Go基礎:配列とスライス

Go入門配列スライス
広告エリア

配列

固定長のデータ構造です。

// 配列の宣言
var numbers [5]int  // ゼロ値で初期化
fmt.Println(numbers)  // [0 0 0 0 0]

// 初期値付き
primes := [5]int{2, 3, 5, 7, 11}
fmt.Println(primes)  // [2 3 5 7 11]

// 要素数を自動推論
vowels := [...]string{"a", "e", "i", "o", "u"}
fmt.Println(len(vowels))  // 5

// 要素へのアクセス
fmt.Println(primes[0])  // 2
primes[0] = 1

配列の走査

numbers := [5]int{1, 2, 3, 4, 5}

// インデックスと値
for i, v := range numbers {
    fmt.Printf("index: %d, value: %d\n", i, v)
}

// 値のみ
for _, v := range numbers {
    fmt.Println(v)
}

配列は値型

original := [3]int{1, 2, 3}
copy := original  // コピーが作成される
copy[0] = 100

fmt.Println(original)  // [1 2 3](変更されない)
fmt.Println(copy)      // [100 2 3]

スライス

可変長のデータ構造です。配列の参照として動作します。

// スライスの作成
var slice []int  // nil スライス
fmt.Println(slice == nil)  // true

// リテラルで作成
numbers := []int{1, 2, 3, 4, 5}

// makeで作成
slice2 := make([]int, 5)      // 長さ5、容量5
slice3 := make([]int, 3, 10)  // 長さ3、容量10

スライス操作

numbers := []int{1, 2, 3, 4, 5}

// 要素へのアクセス
fmt.Println(numbers[0])  // 1
numbers[0] = 10

// 長さと容量
fmt.Println(len(numbers))  // 5
fmt.Println(cap(numbers))  // 5

// 追加
numbers = append(numbers, 6)
numbers = append(numbers, 7, 8, 9)

// スライスを追加
more := []int{10, 11, 12}
numbers = append(numbers, more...)

スライス式

numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

// 部分スライス
fmt.Println(numbers[2:5])   // [2 3 4]
fmt.Println(numbers[:3])    // [0 1 2]
fmt.Println(numbers[7:])    // [7 8 9]
fmt.Println(numbers[:])     // [0 1 2 3 4 5 6 7 8 9]

// 3インデックス式(容量を制限)
limited := numbers[2:5:7]  // [2 3 4]、容量5

スライスのコピー

src := []int{1, 2, 3}
dst := make([]int, len(src))
copy(dst, src)

dst[0] = 100
fmt.Println(src)  // [1 2 3](変更されない)
fmt.Println(dst)  // [100 2 3]

スライスの削除

numbers := []int{0, 1, 2, 3, 4, 5}

// インデックス2の要素を削除
i := 2
numbers = append(numbers[:i], numbers[i+1:]...)
fmt.Println(numbers)  // [0 1 3 4 5]

マップ

キーと値のペアを格納するデータ構造です。

// マップの作成
var m map[string]int  // nil マップ

// リテラルで作成
scores := map[string]int{
    "太郎": 85,
    "花子": 92,
}

// makeで作成
m = make(map[string]int)

// 要素の追加・更新
scores["次郎"] = 78

// 要素の取得
score := scores["太郎"]
fmt.Println(score)  // 85

// 存在確認
score, ok := scores["三郎"]
if ok {
    fmt.Println(score)
} else {
    fmt.Println("存在しません")
}

// 削除
delete(scores, "次郎")

// 長さ
fmt.Println(len(scores))

マップの走査

scores := map[string]int{
    "太郎": 85,
    "花子": 92,
    "次郎": 78,
}

for key, value := range scores {
    fmt.Printf("%s: %d\n", key, value)
}

// キーのみ
for key := range scores {
    fmt.Println(key)
}

マップとスライスの組み合わせ

// スライスを値に持つマップ
groups := map[string][]string{
    "fruits":     {"apple", "banana", "orange"},
    "vegetables": {"carrot", "potato"},
}

groups["fruits"] = append(groups["fruits"], "grape")

// マップのスライス
users := []map[string]string{
    {"name": "太郎", "email": "taro@example.com"},
    {"name": "花子", "email": "hanako@example.com"},
}

実践例:単語カウント

package main

import (
    "fmt"
    "strings"
)

func wordCount(text string) map[string]int {
    counts := make(map[string]int)
    words := strings.Fields(strings.ToLower(text))

    for _, word := range words {
        counts[word]++
    }

    return counts
}

func main() {
    text := "Go is great Go is simple Go is fast"
    counts := wordCount(text)

    for word, count := range counts {
        fmt.Printf("%s: %d\n", word, count)
    }
}

実践例:スタックとキュー

package main

import "fmt"

// スタック(LIFO)
type Stack []int

func (s *Stack) Push(v int) {
    *s = append(*s, v)
}

func (s *Stack) Pop() (int, bool) {
    if len(*s) == 0 {
        return 0, false
    }
    index := len(*s) - 1
    value := (*s)[index]
    *s = (*s)[:index]
    return value, true
}

// キュー(FIFO)
type Queue []int

func (q *Queue) Enqueue(v int) {
    *q = append(*q, v)
}

func (q *Queue) Dequeue() (int, bool) {
    if len(*q) == 0 {
        return 0, false
    }
    value := (*q)[0]
    *q = (*q)[1:]
    return value, true
}

func main() {
    // スタック
    var stack Stack
    stack.Push(1)
    stack.Push(2)
    stack.Push(3)
    v, _ := stack.Pop()
    fmt.Println(v)  // 3

    // キュー
    var queue Queue
    queue.Enqueue(1)
    queue.Enqueue(2)
    queue.Enqueue(3)
    v, _ = queue.Dequeue()
    fmt.Println(v)  // 1
}

まとめ

  • 配列は固定長、型に長さが含まれる
  • スライスは可変長、配列の参照
  • makeでスライス・マップを初期化
  • appendでスライスに要素追加
  • copyでスライスをコピー
  • マップはmap[KeyType]ValueType
  • 存在確認はvalue, ok := m[key]
  • rangeでイテレート

次回は構造体について学びます。

広告エリア