質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Q&A

解決済

1回答

1008閲覧

Go言語「A Tour of Go」のsliceでわからないことがあります

退会済みユーザー

退会済みユーザー

総合スコア0

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

0グッド

0クリップ

投稿2018/10/29 19:24

編集2018/10/30 10:43

A Tour of GoでGo言語を学習中、sliceで理解できないところがありました。

「More types: structs, slices, and maps.」の「Slice length and capacity」という項目です。

以下がそのコードです。


package main

import "fmt"

func main() {
s := []int{2, 3, 5, 7, 11, 13} //⑴
printSlice(s) //(1)

// Slice the slice to give it zero length. s = s[:0] //⑵ printSlice(s) //⑵ // Extend its length. s = s[:4] //⑶ printSlice(s) //⑶ // Drop its first two values. s = s[2:] //⑷ printSlice(s) //⑷

}

func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}


で、実行結果がこれです。

len=6 cap=6 [2 3 5 7 11 13] //⑴
len=0 cap=6 []         //⑵
len=4 cap=6 [2 3 5 7]    //⑶
len=2 cap=4 [5 7]      //⑷

コードの⑴、⑵、⑷は理解できます。
(3)がわかりません。

(1)変数sを定義し、lengthが6、capacityが6のsliceをsに代入する。sは[2 3 5 7 11 13]。

(2)sを[:0]でスライスして、sに再代入する。lengthが0、capacityが6になる。sは[]。

(3)sを[:4]でスライスして、sに再代入する。
疑問:⑵でsliceのlengthが0になりました。そのsliceを[:4]でスライスして、なぜ実行結果が len=4 cap=6 [2 3 5 7] になるんでしょうか?なぜ中身が復活してくるのでしょうか?

(4)sを[2:]でスライスして、sに再代入する。lengthが2、capacityが4になる。sは[5 7]。

(2)のコードがなく、(1)→(3)→(4)の順に実行されていれば理解できるのですが...
教えていただけると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

スライスは、

  • 実体の配列(C言語の配列と同じ概念)
  • どの区間にアクセスするのかを示すメタデータ

という二重管理の仕組みになっています。

詳しくはこちらを参照してください。

https://blog.golang.org/go-slices-usage-and-internals

メタデータは以下の三要素

  • 配列の要素へのポインタ
  • スライス長
  • 配列の容量

配列の容量が不足したら新しい配列を大きなサイズでメモリ確保して
元データ参照範囲をコピーします。
ポインタは新しい配列の先頭を指すように変更されます。
質問の例では容量が不足していないのと実体の内容が変更されていないため
以前のデータが復活したかの様になるのです。

投稿2018/10/29 21:47

編集2018/10/30 00:16
nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/10/31 14:14

ご回答ありがとうございます! 参照URLを確認しました。 ものすごく説明が分かりやすくて sliceの概念を理解することができました。 また、参照URLを読みつつ、 A Tour of Goのコードを下記コードに書き換えてみたところ、 疑問に思っていたことが腑に落ちました。 package main import "fmt" func main() { s := []int{2, 3, 5, 7, 11, 13, 15} printSlice(s) s = s[2:5] printSlice(s) // Extend its length. s = s[:4] printSlice(s) // Extend its length. s = s[:5] printSlice(s) // Drop its first two values. s = s[2:] printSlice(s) } func printSlice(s []int) { fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s) } //実行結果 len=7 cap=7 [2 3 5 7 11 13 15] len=3 cap=5 [5 7 11] len=4 cap=5 [5 7 11 13] len=5 cap=5 [5 7 11 13 15] len=3 cap=3 [11 13 15] ご親切にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問