updated on 2020-10-25
配列の宣言 3パターン
① var 変数名 [長さ]型 ② var 変数名 [長さ]型 = [大きさ]型{初期値1, 初期値n} ③ 変数名 := [...]型{初期値1, 初期値n}
package main import "fmt" func main(){ // パターン① var arr[2] string arr[0] = "Golange" arr[1] = "Java" // パターン② var arr[2] string = [2]string {"Golang", "Java"} // パターン③ arr := [...] string{"Golang", "Java"} fmt.Println(arr[0], arr[1]) //=> Golange Java }
配列の初期化
// ゼロ値で初期化 var ns1 [5]int // 配列リテラルで初期化 var ns2 = [5]int{10, 20, 30, 40, 50} // 要素数を値から推論 ns3 := [...]int{10, 20, 30, 40, 50} // 5番目が50、10番目が100で他が0の要素数11の配列 ns4 := [...]int{5: 50, 10: 100}
配列の操作
package main import "fmt" func main(){ ns := [...]int{10, 20, 30, 40, 50} // 要素にアクセス fmt.Println(ns[3]) // インデックス3番目 // 長さ fmt.Println(len(ns)) // スライス演算 fmt.Println(ns[1:4]) // インデックス1~3番目 }
40
5
[20 30 40]
Goの Arrays(配列)は固定長の様な配列である一方、Goの Slices(スライス) は可変長の配列の様な動きをするのでより柔軟にデータ(要素)を格納することが可能
配列の宣言 3パターン
① var 変数名 []型
② var 変数名 []型 = []型{初期値1, ..., 初期値n}
③ 変数名 := 配列[start:end] //配列(またはスライス)のstartから(end - 1)を取り出す事でスライスを作成する。
① var slice []string ② slice := [] string{"Golang", "Java"} ③ arr := [...] string{"Golang", "Java"} slice := arr[0:2]
スライスの初期化
package main import "fmt" func main() { // ゼロ値はnil var ns1 []int fmt.Println(ns1) // 長さと容量を指定して初期化 // ゼロ値で初期化 ns1 = make([]int, 3, 10) fmt.Println(ns1) // スライスリテラルで初期化 // 要素数は指定しなくてよい // 自動で配列は作られる var ns2 = []int{10, 20, 30, 40, 50} fmt.Println(ns2) // 5番目が50、10番目が100で他が0の要素数11のスライス ns3 := []int{5: 50, 10: 100} fmt.Println(ns3) }
(コンソール出力)
[]
[0 0 0]
[10 20 30 40 50]
[0 0 0 0 0 50 0 0 0 0 100]
スライスの操作
操作 | 意味 |
---|---|
Slice[start:end] | start から end - 1 まで |
Slice[start:] | start から最後尾まで |
Slice[:end] | 先頭から end - 1 まで |
Slice[:] | 先頭から最後尾まで |
package main import "fmt" func main() { ns := []int{10, 20, 30, 40, 50} n, m := 2, 4 // インデックス2番目からスライスを取得する fmt.Println(ns[n:]) // [30 40 50] // 先頭からインデックス3番目までのスライスを取得する fmt.Println(ns[:m]) // [10 20 30 40] // capを指定する ms := ns[:m:m] fmt.Println(cap(ms)) // 4 }
スライス操作を行う場合は生成元の配列(またはスライス)と要素を共有します。
つまり、スライスの要素を変更すると、その元となる配列の対応する要素が変更されます。
func main(){ arr := [...] string{"Golang", "Java"} slice := arr[0:2] //スライスの作成 slice[0] = "Ruby" //slice[0]の要素を変更 fmt.Println(slice) //[Ruby Java] fmt.Println(arr) // arrも[Ruby Java]に変更されている }
(コンソール出力)
[Ruby Java]
[Ruby Java]
package main import "fmt" func main(){ ns := []int{10, 20, 30, 40, 50, 60} // 長さ fmt.Printf("サイズ => %d\n", len(ns)) fmt.Printf("要素追加前のcapacity => %d\n", cap(ns)) // 要素の追加 // 容量が足りない場合は背後の配列が再確保される ns = append(ns, 70, 80) // 容量 fmt.Printf("要素追加後のcapacity => %d\n", cap(ns)) }
Goでは配列は宣言時に要素の数が固定されるので要素の追加はできない。スライスの場合は追加可能。
スライスに要素を追加したい場合は組み込み関数 append()
を使用する事で簡単に行える。
appendの挙動
package main import "fmt" func main() { a := []int{10, 20} fmt.Println(a, cap(a)) // [10 20] 2 b := append(a, 30) a[0] = 100 fmt.Println(a, cap(a)) // [100 20] 2 fmt.Println(b, cap(b)) // [10 20 30] 4 c := append(b, 40) b[1] = 200 fmt.Println(c, cap(c)) // [10 200 30 40] 4 }
スライス演算
package main import "fmt" func main() { ns := []int{10, 20, 30, 40, 50} n, m := 2, 4 // n番目以降のスライスを取得する fmt.Println(ns[n:]) // [30 40 50] // 先頭からm-1番目までのスライスを取得する fmt.Println(ns[:m]) // [10 20 30 40] // capを指定する ms := ns[:m:m] fmt.Println(cap(ms)) // 4 }
要素の削除
a = append(a[:i], a[j+1:]...)
aのi-1番目までのスライスに、j+1番目以降を追加下スライスを取得
=> i~j番目がカットされる
(例)
package main
import "fmt"
func main(){
a := []int{10, 20, 30, 40, 50, 60}
i, j := 1, 3
a = append(a[:i], a[j+1:]...)
fmt.Printf("a: %v\n", a) // a: [10 40 50 60]
}
a = append(a[:i], a[i+1:]...) // or a = a[:i+copy(a[i:], a[i+1:])]
(例)
package main import "fmt" func main(){ a := []int{10, 20, 30, 40, 50, 60} i := 2 // 方法① //fmt.Println(copy(a[i:], a[i+1:]), a) // 3(コピーした要素の数) [10 20 40 50 60 60](スライスaの値) a = a[:i+copy(a[i:], a[i+1:])] // // 方法② // a = append(a[:i], a[i+1:]...) // fmt.Printf("a: %v\n", a) // a: [10 20 40 50 60] }
初期化
// ゼロ値はnil var m map[string]int // makeで初期化 m = make(map[string]int) // 容量を指定できる m = make(map[string]int, 10) // リテラルで初期化 m := map[string]int{"x": 10, "y": 20} // 空の場合 m := map[string]int{}
マップの操作
package main func main() { m := map[string]int{"x": 10, "y": 20} // キーを指定してアクセス println(m["x"]) // キーを指定して入力 m["z"] = 30 // 存在を確認する n, ok := m["z"] println(n, ok) // キーを指定して削除する delete(m, "z") // 削除されていることを確認 n, ok = m["z"] // ゼロ値とfalseを返す println(n, ok) }
(コンソール出力)
10
30 true
0 false
要素がコンポジット型
ひとことで表すと、複数のデータ型を1つのデータ型にまとめてものである。
Go言語における具体的なコンポジット型を以下にまとめた。
種類 | 説明 |
---|---|
配列 | 同じ型のデータを並べたデータ型 |
スライス | 可変長な配列 |
マップ | キーと値を連結させたデータ型 |
構造体 | 異なるデータ型を集めたデータ型 |
A struct {
N int
}
}
ユーザー定義型
typeで名前を付けて新しい型を定義する
type 型名 基底型
// 組み込み型を基にする type MyInt int // 他のパッケージの型を基にする type MyWriter io.Writer // 型リテラルを基にする type Person struct { Name string }
ユーザー定義型の特徴
type MyInt int var n int = 100 m := MyInt(n) n = int(m)
型のエイリアス
type Applicant = http.Client
type Applicant = http.Client func main() { fmt.Printf("%T", Applicant{}) }