空のスライスを初期化する正しい方法


227

サイズが固定されていない空のスライスを宣言するには、次のようにします。

mySlice1 := make([]int, 0)

または:

mySlice2 := []int{}

どちらが正しい方法か疑問に思います。


2
あなたは「固定されていないサイズ」と言いますが、スライスが固定サイズになること決してありません。容量がゼロの場合を除きます。注意が必要な容量のアイデア/推測/ヒントがある場合は、3つの引数のバージョンを使用することをお勧めします。例えば、マップキーのスライスを構築するために:keys := make([]int, 0, len(m)); for k, v := range m { keys := append(keys,k) }
デイブC

回答:


272

あなたが与えた2つの選択肢は意味的に同じですが、使用make([]int, 0)するとruntime.makesliceへの内部呼び出しが発生します(Go 1.14)。

また、nil値を残すこともできます。

var myslice []int

Golang.orgブログに書かれているように

nilスライスは、何も指していない場合でも、機能的に長さゼロのスライスと同等です。長さはゼロで、割り当てにより追加できます。

nilスライスしかしうjson.Marshal()"null"、空のスライス一方にマーシャリングう"[]"@farwayerにより指摘したように、。

@ArmanOrdookhaniによって指摘されているように、上記のオプションのいずれも割り当てを引き起こしません。



106
介護こと:json.Marshal()返されるnullためvar myslice []int[]初期化されたスライスのためにmyslice := []int{}
farwayer

10
また、注意してください:reflect.DeepEqualnilのスライスと非nilのスライスの区別が作る:a := []int{}var b []intreflect.DeepEqual(a, b) // returns false
asgaines

1
なぜそれが割り当てを行うと思いますか?キャップはゼロなので、何も割り当てられません。長さがゼロのものへのすべてのポインターは、メモリ内の同じ場所を指し
Arman Ordookhani

1
@ArmanOrdookhaniあなたは正しいです。私はそれを試してみました、そしてまた、私は同一の組立て指示に関する私の仮定に誤りがあることを知りました。修繕!
ANisus

65

それらは同等です。このコードを参照してください:

mySlice1 := make([]int, 0)
mySlice2 := []int{}
fmt.Println("mySlice1", cap(mySlice1))
fmt.Println("mySlice2", cap(mySlice2))

出力:

mySlice1 0
mySlice2 0

両方のスライスに0容量があるため、両方のスライスに0長さがあり(容量を超えることはできません)、両方のスライスに要素がないことを意味します。つまり、2つのスライスはすべての面で同一です。

同様の質問を参照してください:

golangでnilスライスとemptyスライスを持つことの意味は何ですか?

Go言語でのnilスライスとnon-nilスライスvs空のスライス


46

@ANisusの回答への追加として...

以下は、言及する価値があると思う"Go in action"の本からの情報です。

nilemptyスライスの違い

次のようなスライスについて考えると、

[pointer] [length] [capacity]

次に:

nil slice:   [nil][0][0]
empty slice: [addr][0][0] // points to an address

ゼロスライス

スライスを返す関数で例外が発生した場合など、存在しないスライスを表現する場合に便利です。

// Create a nil slice of integers.
var slice []int

空のスライス

空のスライスは、データベースクエリがゼロの結果を返す場合など、空のコレクションを表す場合に役立ちます。

// Use make to create an empty slice of integers.
slice := make([]int, 0)

// Use a slice literal to create an empty slice of integers.
slice := []int{}

かかわらず、あなたは組み込み関数はnilスライスまたは空のスライスを使用しているかどうかのappendlencap同じように機能します。


遊び場に行く例

package main

import (
    "fmt"
)

func main() {

    var nil_slice []int
    var empty_slice = []int{}

    fmt.Println(nil_slice == nil, len(nil_slice), cap(nil_slice))
    fmt.Println(empty_slice == nil, len(empty_slice), cap(empty_slice))

}

プリント:

true 0 0
false 0 0

空のスライスのアドレスを1つのステップで取得できますmakeか?
Simin Jie

我々は、機能を見てみましょう場合は、署名makeアドレスを返すようには見えません。あなたは一歩でそれを行うことはできないと思います。
tgogos 2018

13

Goで空のスライスとnilスライスは異なる方法で初期化されます。

var nilSlice []int 
emptySlice1 := make([]int, 0)
emptySlice2 := []int{}

fmt.Println(nilSlice == nil)    // true
fmt.Println(emptySlice1 == nil) // false
fmt.Println(emptySlice2 == nil) // false

3つのスライスすべてについて、lenとcapは0です。


make([]int, 0)Jetbrains GoLandは、の場合のように「不要」であると文句を言わないので、最高です[]int{}。これは、単体テストの作成に役立ちます。
Andrzej Rehmann 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.