Go言語基礎 その5 Go言語の基本構文3 (配列, interface, slice, map, 型アサーション, Defined type, Type alias)

はじめに

前回の続きで Go 言語の文法をまとめておきたいと思います。

Go言語文法

その他の基本型

  • 配列型 []
  • interface{} 型 interface{} すべての型と互換
  • nil 型 nil
// 配列型
a1 := [5]int{1, 2, 3, 4, 5}
fmt.Printf("%v", a1) // => [1, 2, 3, 4, 5]
a[1] = 3
a[5] = 6 // runtime error
a[-1] = 3 // runtime error

// ... で 要素数を省略できる
a2 := [...]int{1, 2, 3} // == [3]int{1, 2, 3}

// interface{} 型
var x1 interface{} = 3.14

// interface{} 型
// ゼロ値はnil
var x2 interface{} // nil

slice(スライス)

// sliceのゼロ値はnil
var s1 []int // == nil

// makeで生成
s2 := make([]int, 5, 30) // 要素数5, 容量30 の int型のスライスを生成

// len, capで要素数、容量を取得できる
len(s2) // == 5
cap(s2) // == 30

fmt.Println(s2) // => [0, 0, 0, 0, 0]

// index access
s2[0] = 1
s2[1] = 2

fmt.Println(s2) // => [1, 2, 0, 0, 0]

// 簡易スライス式
s3 := s2[0:2] // s3 == [1, 2]
s4 := s2[:3] // s3 == [1, 2, 0]
s5 := s2[2:] // s3 == [0, 0, 0]
s6 := s2[:] // s3 == [1, 2, 0, 0, 0]

// 文字列の簡易スライス式
// []byteであるとみなした上で処理
s7 := "あいうえお"[3:9] // s == "いう"

// append で slice の末尾に追加
s2 = append(s2, 3) // s2 == [1, 2, 0, 0, 0, 3]
s2 = append(s2, s3...) // s2 == [1, 2, 0, 0, 0, 3, 1, 2]

// copy
// コピー先の要素分だけコピーが実行される
i1 := []int{1, 2, 3, 4, 5}
i2 := []int{11, 12}
copy(i2, i1) // i2 == [1, 2]

// 可変長引数とスライス
func output(args ...string) {
    for _, s := range args {
        fmt.Println(s)
    }
}
output("Apple", "Banana", "Cherry")
s8 := ["Apple", "Banana", "Cherry"]
// 配列を展開して渡す場合 ... をつける
output(s8...)

配列は値渡し、スライスは参照渡しで別物
スライスはもとの配列を共有することがあるので注意

a1 := []int{1, 2, 3, 4, 5}
a2 := a1[0:2] // a2 == [1, 2]
// a2の値も変更されている
a1[1] = 0 // a2 == [1, 0]

map(マップ)

// 宣言
var m map[int]string

// 要素の代入
m[1] = "Hoge"
m[2] = "Fuga"
m[1] = "Piyo"  // キーが重複すると上書きされる

fmt.Println(m) // => map[1:Piyo 2:Fuga]

// 要素の参照
i := m[7] // i == 0

s, ok := m[1] // s == "Hoge", ok == true
s, ok := m[4] // s == "", ok == false

len(m) // == 3
delete(m, 2)
delete(m, 3) // 何も行われない
fmt.Println(m) // => map[1:Piyo]

キーと要素のペアをまとめて生成する書き方

m := map[int]string{
    1: "Hoge",
    2: "Fuga",
    3: "Piyo",
}

省略記法

m := map[int]map[float64]string{
    1: {3.14: "円周率"}
}

範囲節による for はキーの順序は保証されない

m := map[int]string{
    1: "Hoge",
    2: "Fuga",
    3: "Piyo",
}
for _, str := range m {
    // Hoge -> Fuga -> Piyoの順で表示されるとは限らない
    // 順序不定
    fmt.Println(str)
}

型アサーション

  • インターフェースの値が特定の型を保持しているかどうかををチェックできます。
  • 保持していれば、値と true を返します。保持していない場合、ゼロ値と false が返されます。
  • value, ok := x.(type) のように 2 つめの戻り値を ok にする慣例があります
var x interface{} = 3.14
i, ok := x.(int) // i == 0, ok == false

Defined type と Type alias

// 別名として定義 (Defined type)
// 完全に違う型として扱われる
type MyInt int
// 型エイリアス (Type alias)
// 異なる名前で同じ型
type MyFloat = float

参考にした本

おわりに

次回は Go 言語の文法の続きを復習したいと思います。