24

私はしばらくGoを試してきましたが、この質問は私を悩ませ続けています。スライスにやや大きなデータセット (たとえば、1000 万の int64) を構築するとします。

package main

import (
    "math"
    "fmt"
)

func main() {
    var a []int64
    var i int64;
    upto := int64(math.Pow10(7))
    for i = 0; i < upto; i++ {
        a = append(a, i)
    }
    fmt.Println(cap(a))
}

しかし、私はそれらのほとんどを必要としないと判断したので、最終的にそれらの 10 個だけをスライスしたいと思います。Go の wiki でスライスと削除の両方の手法を試しましたが、いずれもスライスの容量を減らすようには見えません。

それが私の質問です.Goにはrealloc()、Cの同じポインターに対する以前の呼び出しよりも小さいサイズの引数を使用して、スライスの容量を縮小する実際の方法はありませんか? それは問題であり、どのように対処する必要がありますか?

4

6 に答える 6

7

Go にはスライスを縮小する方法がありません。ほとんどの場合、これは問題ではありませんが、メモリの使用状況をプロファイルして、使用量が多すぎることがわかった場合は、次のように対処できます。

まず、必要なサイズのスライスを作成し、そこにデータをコピーできます。その後、ガベージ コレクターは大きなスライスを解放します。ビルトインをコピー

第 2 に、大きなスライスを生成するたびに再利用できるため、複数回割り当てることはありません。

最後に、1e7代わりに を使用できますmath.Pow10(7)

于 2013-05-25T09:59:57.213 に答える
3

この例を見てみましょう:

func main() {
    s := []string{"A", "B", "C", "D", "E", "F", "G", "H"}
    fmt.Println(s, len(s), cap(s))  // slice, length, capacity

    t := s[2:4]
    fmt.Println(t, len(t), cap(t))

    u := make([]string, len(t))
    copy(u, t)
    fmt.Println(u, len(u), cap(u))
}

次の出力が生成されます。

[A B C D E F G H] 8 8
[C D] 2 6
[C D] 2 2

s8本の弦を保持するスライスです。t部分を保持するスライスです[C D]。の長さtは 2 ですが、 と同じ隠し配列を使用するためs、その容量は 6 ("C" から "H" まで) です。[C D]問題は、の隠し配列から独立したスライスをどのように持つsかです。長さ 2 の文字列の新しいスライス ( slice ) を作成し、その内容をto にuコピーするだけです。の基になる隠し配列は、の隠し配列とは異なります。tuus

最初の問題は次のとおりです。大きなスライスがあり、その上に新しい小さなスライスを作成します。小さい方のスライスは同じ隠し配列を使用するため、ガベージ コレクターは隠し配列を削除しません。

詳細については、この投稿の下部を参照してください: http://blog.golang.org/go-slices-usage-and-internals .

于 2014-02-07T19:18:19.837 に答える