スライスを宣言するか、スライスを作成しますか?


98

Golangでは、違いは何であるvar s []intとはs := make([]int, 0)

どちらも機能することがわかりましたが、どちらが優れていますか?


最初のものはnilスライスを作成するのに対し、2番目のものはemptyスライスを作成します(これは「アクションブックの実行」で使用される用語です)。ここでも同じ回答を投稿しないようにするには、stackoverflow.com
a / 45997533/1561148を

回答:


94

fabriziom回答に加えて、「Go Slices:usage and internals」で他の例を見ることができます[]int

スライスのゼロ値(nil)は長さゼロのスライスのように機能するため、スライス変数を宣言してループに追加することができます。

// Filter returns a new slice holding only
// the elements of s that satisfy f()
func Filter(s []int, fn func(int) bool) []int {
    var p []int // == nil
    for _, v := range s {
        if fn(v) {
            p = append(p, v)
        }
    }
    return p
}

これは、スライスに追加する、ということを意味、あなたは最初にメモリを割り当てる必要はありません:nilスライスはp int[]スライスがに追加するように十分です。


なぜそれが割り当てを行うと思いますか?キャップはゼロなので、makeの有無にかかわらず何も割り当てられません。
Arman Ordookhani

1
@ArmanOrdookhani同意する。var p []int使用するよりも宣言の方が簡単だmakeと思います(0キャップを指定しても何も割り当てられない場合でも、割り当てに関連付けます)。読みやすさの点で、私はmakeここを使用しないことを好みます。
VonC

私はどこでもリテラルを使用する方が好きです(例えばp := []int{})。通常:=、ほとんどの変数を宣言するために構文を使用するため、スライスに例外を設けるのではなく、どこにでもそれを置く方が自然です。これ以外に、割り当てについて考えようとすると、通常、人々は時期尚早の最適化に向かいます。
Arman Ordookhani

113

簡単な宣言

var s []int

はメモリを割り当てず、をsポイントしますがnil

s := make([]int, 0)

s0要素のスライスにメモリを割り当て、メモリをポイントします。

通常、ユースケースの正確なサイズがわからない場合は、最初の方が慣用的です。


地図についても同じことが言えますか?var m map [string] int vs m:= make(map [string] int)?ありがとう。
ジョシュア2015年

11
いや、あなたはmakeマップする必要がありますmap。何もないのに、簿記のために割り当てられたスペースが必要だからです。
twotwotwo 2015

11
( 'nil'ではなく)0要素のスライスを返す必要がある場合は、makeが正しい使用法です。
ジェス

6
APIを構築していて、配列を応答として返すnil場合、空の配列ではなくスライスに要素がない場合に宣言型を使用すると戻ります。ただし、makeを使用してスライスを作成すると、代わりに空の配列が返されます。これは通常、望ましい効果です。
robinmitra

6
この回答に関するコメントで述べたように:stackoverflow.com/a/29164565/1311538、jsonマーシャリングなどを実行しようとすると、違いがあります。nilスライス(var s []intnullをマーシャリングすると、が生成され、空のスライス(s := make([]int, 0))をマーシャリングすると、期待どおりの結果が得られます[]
エイジズ

8

違いを見つけました。使用する場合

var list []MyObjects

その後、あなたはあなたが得る、JSONとして出力をエンコードしますnull

list := make([]MyObjects, 0)

[]期待通りの結果になります。


ええ、後者はnullではなく[]配列で応答したいときに非常に便利です
Nhan Tran

4

もう少し完全に(のもう1つの引数make)の例:

slice := make([]int, 2, 5)
fmt.Printf("length:  %d - capacity %d - content:  %d", len(slice), cap(slice), slice)

でる:

length:  2 - capacity 5 - content:  [0 0]

または動的タイプslice

slice := make([]interface{}, 2, 5)
fmt.Printf("length:  %d - capacity %d - content:  %d", len(slice), cap(slice), slice)

でる:

length:  2 - capacity 5 - content:  [<nil> <nil>]

2
良い例。+1
VonC 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.