2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Go初心者のためのメモ(ややこしい配列編)

Last updated at Posted at 2019-07-09

はじめに

go言語初心者のための記事です。
公式チュートリアルの大事なところをまとめただけです。
この記事では配列、および配列に似たものをまとめます。
array、slice、mapの3つです。

ややこしいGoにおける配列の概念

Goには二つの配列表現arrayとsliceがある。
とてもややこしいが、公式チュートリアル曰く、

  • 固定長がarray(=配列)
  • 可変長がslice

という定義らしい。

配列(array)

Goの配列(array)は必ず配列の長さを指定する。
array[i:j]という書き方でiからj前までの要素を取得できる。

var a [10]int
b := [6]int{2, 3, 5, 7, 11, 13}
fmt.Println(b[0:3]) // [2 3 5]を返す

また、b[0:6]は、b[:6]b[0:]b[:]という書き方と等価。

可変長な配列(slice)

python等の配列のような可変長の配列をGoではsliceと呼ぶ。
混乱を避けるためここではそれぞれarray、sliceと呼ぶこととする。

var s[]int // 空のsliceを生成
fmt.Println(s) // []を返す

array := [6]int{2, 3, 5, 7, 11, 13}
var slice[]int = array[1:4]
fmt.Println(s) // [3 5 7]を返す

arrayからsliceへと代入した場合、sliceはそのarrayの一部として振る舞う。
つまり、sliceの変更はarrayにも反映される。
日本語下手なので下記の例を見てください。

array := [6]int{2, 3, 5, 7, 11, 13}
var slice[]int = array[1:4]

slice[0] = 0
fmt.Println(slice) // [0 5 7]を返す
fmt.Println(array) // [2 0 5 7 11 13]を返す

s := []int{1, 2, 3} // :=演算子を使うとこのように書ける

多次元のslice

空行列[]の数でsliceの次元を表現できる。

slice := [][]string{
	[]string{"犬", "猫", "猿"},
	[]string{"りんご", "ばなな", "パイナップル"},
	[]string{"男", "女", "あいつ"},
}
fmt.Println(slice[1][2]) // パイナップルを返す

sliceの長さと容量

sliceには長さ(length)と容量(capacity)という概念がある。
長さ(length)はどの言語にもよくある配列の長さのようなもの。
容量(capacity)は聞いたことなかったが考え方は簡単で、
元のarrayの長さ - arrayから取得し始めたsliceの要素のインデックス
ってだけ。
これも実行して確認するほうが理解が早い。

array := [6]int{2, 3, 5, 7, 11, 13}
var slice[]int = array[1:4]
fmt.Println(len(slice)) // 3を返す 
fmt.Println(cap(slice)) // 5を返す(6-1=5)

s := []int{2, 3, 5, 7} // この定義の場合、元のarrayも{2, 3, 5, 7}となる
s = s[1:3]
fmt.Println(len(s)) // 2を返す
fmt.Println(cap(s)) // 3を返す(4-1=2) 

sliceを操作する便利な関数

sliceの初期化(make)

make関数によって、全ての要素に0が代入されたsliceを生成することができる。
引数は以下のとおり。
make(型, sliceの長さ, sliceの容量)
3番目の引数であるsliceの容量のみ省略できる。

a := make([]int, 5)  // len(a)=5
b := make([]int, 0, 5) // len(b)=0, cap(b)=5
fmt.Println(a) // [0 0 0 0 0]を返す

sliceへの要素の追加(append)

append関数で要素の追加を行える。
引数は以下のとおり。
append(追加する対象, 追加する要素, 追加する要素, ...)

var s []int
s = append(s, 0, 1, 2, 3)
fmt.Println(s) // [0 1 2 3]を返す

sliceの要素にそれぞれアクセス(range)

range sliceという記述でsliceの要素にそれぞれアクセスできる。
range関数の戻り値はインデックスと要素の値であることに注意。
for文と組み合わせた例は以下のとおり。

main.go
package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16}

func main() {
	for i, v := range pow {
		fmt.Printf("2**%d = %d\n", i, v)
	}
}
/* 実行結果
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
*/

インデックスや値を_に代入することで、それを使用しないことを明示する粋な表記もある。

for _, value := range pow {
	fmt.Printf("%d\n", value)
}

map型

配列と似たmap型の定義等も残しておく。
pythonでいう辞書型と一緒でkeyとvalueという概念が存在する。

定義の仕方

map[keyの型]valueの型{key: value}で定義できる。

m := map[string]string{
	"key1": "value1",
	"key2": "value2",
	"key3": "value3",
}
fmt.Println(m["key1"]) // value1を返す

n := make(map[string]string) // make関数で定義する場合

要素の削除(delete)

delete関数で指定したkeyを削除できる。
引数はdelete(対象のmap、削除したいkey)とする。
引数を増やして複数のkeyを同時に削除することはできない。

m := map[string]string{
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
}
delete(m, "key1")
fmt.Println(m) // map[key2:value2 key3:value3]を返す

keyが存在するかどうかの確認

指定したkeyにvalueが存在するかどうかの確認は以下の記述で行える。

m := make(map[string]string)
value, ok := m["key1"] // 指定したkeyの値と、指定したkeyが存在するかどうかのbool値をそれぞれ代入
fmt.Println(value) // 0を返す
fmt.Println(ok) // falseを返す
2
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?