Taka blog

プログラミングとか

[golang]sliceの操作方法一覧

sliceの型はstringとします。

宣言

slice := make([]string, 0, 100)

第2引数に初期要素数、第3引数に容量を指定します。

初期要素数を1以上にすると、要素にはゼロ値が入ります。

宣言時に容量を確保するのは、そうしないと要素を追加して容量オーバーしたときに新しくメモリを確保する無駄が発生してしまうからです。




一部を取り出す

slice := []int{4, 2, 9, 7, 5, 1}
a := slice[2:4] // {9, 7}
b := slice[:1] // {4}
c := slice[4:] // {7, 5, 1}

slice[a:b]はslice[a]からslice[b-1]までをsliceにしたものを指します。slice[b]は含まれないので注意してください。

数字は両者とも省略することができます。1つ目の数字を省略した場合は0が、2つ目の数字を省略した場合はlen(slice)が入る扱いとなります。つまり前者を省略すれば先頭から、後者を省略すれば末尾までの要素が対象です。




要素を追加する

slice = append(slice, "a")
slice = append(slice, []string{"b", "c"}...)

第1引数には元のスライスを指定します。

スライスに1つの要素を追加する場合は、第2引数にスライスの基の型の変数を渡します。複数の要素を追加したい場合は、第2引数にスライスを記述し、その後ろに...を付けます。




スライスをコピーする

i := copy(slice[:3], slice[10:13])

copy()

  • 第1引数のスライスの要素に第2引数のスライスの要素を、先頭から順にコピペ
  • どちらかのスライスが全てコピーorペーストされるとそこで終了
  • コピペに成功した数がint型の戻り値




要素を削除する(並び順を保ちたい場合)

// 削除したいindex
n := 10

// 第2引数の方が少ないので、i は len(slice) - n - 1 と等しい
i := copy(slice[n:], slice[n + 1:])
// copy後、末尾の要素を消す
slice = slice[:len(slice) - 1]

// i + n は len(slice) - 1 と等しいので、上の2行を1文に纏められる
slice = slice[:n + copy(slice[n:], slice[n + 1:])]

// 連続する3つの要素を削除する場合
slice = slice[:n+copy(slice[n:], slice[n+3:])]

// 性能は劣るが分かり易い方法(要素数:1)
slice = append(slice[:n], slice[n+1:]...)

appendを利用すると、メモリアロケーションが発生する可能性があります。


削除されるスライスの要素がポインタ型や、ポインタ型のフィールドを含む構造体である場合、メモリリークが発生します。

これを防ぐには下の例のように、ゼロ値を代入します。

i := copy(slice[n:], slice[n + 1:])
slice[n + i] = nil // 構造体なら、User{}などゼロ値を代入
slice = slice[:n + i]


要素を削除する

slice[n] = slice[len(slice)-1]
slice = slice[:len(slice)-1]

消したい要素を末尾の要素で上書きし、末尾の要素を消しています。




全要素を削除する

slice = slice[0:0]

この操作でsliceは、要素数が0、容量はそのまま、のスライスになります。