9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Go】サブスライスは元スライスとメモリを共有する

Posted at

どんな記事?

Go言語において、スライスの一部分を切り出してサブスライスを作成する場合、データのコピーを作るのではなく2つの変数がメモリを共有することになるため変更を共有するという記事です。
もしオリジナルとはメモリを共有しない独自のスライスを作成する必要がある場合、makeと組み込み関数のcopyを使いましょう。
スライスを一部切り出した場合と、copy関数を使用した場合とでどのような違いがあるか説明していきます。

一部切り出しについて

以下のようにスライスを一部切り出した場合、両者は同じメモリを参照することになります。これはメモリ効率がいいという反面、一方を変えるともう一方にも影響が及ぶことを意味します。

package main

import (
	"fmt"
)


func main() {
	original := []int{1, 2, 3, 4, 5}
	subSlice1 := original[1:3]
	subSlice2 := original[2:4]

	fmt.Println("Before:", original, subSlice1, subSlice2)
	//=> Before: [1 2 3 4 5] [2 3] [3 4]

	subSlice1[0] = 20
	subSlice2[1] = 40

	fmt.Println("After:", original, subSlice1, subSlice2)
	//=> After: [1 20 3 40 5] [20 3] [3 40]
}

一部を切り出したサブスライスの変更によって、オリジナルのスライスの値が変更されていることがわかると思います。
また、以下のコードで同一のメモリを参照していることが確認できます。

func main() {
	original := []int{1, 2, 3, 4, 5}
	subSlice1 := original[1:3]
	subSlice2 := original[2:4]
	fmt.Printf("original address: %p, subSlice1 address: %p\n", &original[1], &subSlice1[0])
	fmt.Printf("original address: %p, subSlice2 address: %p\n", &original[2], &subSlice2[0])
}

copy関数について

copy関数を使用することで、メモリ領域を共有しない独立したスライスにデータをコピーできます。

func main() {
	original := []int{1, 2, 3, 4, 5}
	newSlice1 := make([]int, 2)
	newSlice2 := make([]int, 2)
	copy(newSlice1, original[1:3])
	copy(newSlice2, original[2:4])

	fmt.Println("Before:", original, newSlice1, newSlice2)
	//=> Before: [1 2 3 4 5] [2 3] [3 4]

	newSlice1[0] = 20
	newSlice2[1] = 40

	fmt.Println("After:", original, newSlice1, newSlice2)
	//=> After: [1 2 3 4 5] [20 3] [3 40]
}

また、以下のコードで異なるメモリを参照していることが確認できます。

func main() {
	original := []int{1, 2, 3, 4, 5}
	newSlice1 := make([]int, 2)
	newSlice2 := make([]int, 2)
	copy(newSlice1, original[1:3])
	copy(newSlice2, original[2:4])

	fmt.Printf("original address: %p, subSlice1 address: %p\n", &original[1], &newSlice1[0])
	fmt.Printf("original address: %p, subSlice2 address: %p\n", &original[2], &newSlice2[0])
}

終わりに

今回はSliceの操作について説明しました。これからもGoについての記事を挙げていこうと思っているので、読んでもらえたら嬉しいです。ここまで読んでいただきありがとうございました。

参考記事

9
3
0

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
9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?