วิธีที่ถูกต้องในการเริ่มต้นชิ้นส่วนที่ว่างเปล่า


227

หากต้องการประกาศชิ้นว่างเปล่าที่มีขนาดไม่คงที่จะทำอย่างไรดีกว่า:

mySlice1 := make([]int, 0)

หรือ:

mySlice2 := []int{}

แค่สงสัยว่าอันไหนเป็นวิธีที่ถูกต้อง


2
คุณพูดว่า "ขนาดไม่คงที่" แต่ชิ้นจะไม่ได้ขนาดคงที่ เว้นแต่คุณจะหมายถึงศูนย์ความจุ หมายเหตุหากคุณมีความคิด / คาดเดา / คำใบ้ว่าคุณอาจต้องการความจุเท่าใดการใช้เวอร์ชันอาร์กิวเมนต์สามตัวนั้นดี เช่นสร้างส่วนของปุ่มแผนที่:keys := make([]int, 0, len(m)); for k, v := range m { keys := append(keys,k) }
Dave C

1
มีความซ้ำซ้อนของDeclare slice หรือ slice?
ผู้ใช้

คำตอบ:


272

ทางเลือกสองทางที่คุณให้มามีความหมายเหมือนกัน แต่การใช้make([]int, 0)จะส่งผลให้เกิดการเรียกภายในไปยังruntime.makeslice (ไป 1.14)

คุณมีตัวเลือกที่จะปล่อยให้มันมีnilค่า:

var myslice []int

ดังที่เขียนไว้ในบล็อก Golang.org :

ชิ้นศูนย์จะทำหน้าที่เทียบเท่ากับชิ้นศูนย์ที่มีความยาวแม้ว่ามันจะชี้ไปที่อะไรก็ตาม มันมีความยาวเป็นศูนย์และสามารถผนวกเข้ากับการจัดสรร

nilอย่างไรก็ตามจะมีการแบ่งส่วนjson.Marshal()ใน"null"ขณะที่ส่วนที่ว่างเปล่าจะจัดเข้า"[]"ตำแหน่งตาม @farwayer

ไม่มีตัวเลือกใด ๆ ด้านบนที่จะทำให้เกิดการจัดสรรตามที่ระบุโดย @ArmanOrdookhani


4
ยังกล่าวถึง wiki github.com/golang/go/wiki/…
Grzegorz Żur

106
ได้รับการดูแล: json.Marshal()จะกลับมาnullสำหรับvar myslice []intและ[]สำหรับชิ้นที่เริ่มmyslice := []int{}
farwayer

10
นอกจากนี้ยังต้องระวัง: reflect.DeepEqualทำให้ความแตกต่างระหว่างชิ้นศูนย์และชิ้นไม่ใช่ศูนย์: a := []int{}, var b []int,reflect.DeepEqual(a, b) // returns false
asgaines

1
ทำไมคุณคิดว่าจะจัดสรร? ขีด จำกัด ศูนย์จึงไม่มีการจัดสรรอะไรเลย ตัวชี้ทั้งหมดเป็นศูนย์ความยาวชี้ไปที่ตำแหน่งเดียวกันในหน่วยความจำ: play.golang.org/p/MPOKKl_sYvw
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 ชิ้นเหมือนกันในทุกด้าน

ดูคำถามที่คล้ายกัน:

อะไรคือจุดของการไม่มีศูนย์และชิ้นส่วนเปล่าในโกลัน?

ไม่มีส่วนใดเทียบกับส่วนที่ไม่ใช่แบบไม่มีส่วนเทียบกับส่วนที่ว่างในภาษาโก


46

เป็นส่วนเสริมของ@ANisus 'คำตอบ ...

ด้านล่างเป็นข้อมูลบางส่วนจากหนังสือ"ดำเนินการ"ซึ่งฉันคิดว่าน่าพูดถึง:

ความแตกต่างระหว่างnil& emptyชิ้น

ถ้าเราคิดถึงชิ้นเช่นนี้:

[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{}

ไม่ว่าคุณกำลังใช้ชิ้นศูนย์หรือชิ้นที่ว่างเปล่าในตัวฟังก์ชั่นappend, lenและcapทำงานเดียวกัน


ไปสนามเด็กเล่นตัวอย่าง :

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

เราสามารถรับที่อยู่ของชิ้นเปล่าในขั้นตอนเดียวได้makeหรือไม่?
Simin Jie

ถ้าเราใช้เวลาดูที่ฟังก์ชั่นที่ลายเซ็น , makeดูเหมือนจะไม่ได้กลับมาอยู่ ฉันเชื่อว่าคุณไม่สามารถทำได้ในขั้นตอนเดียว
tgogos

13

ชิ้นส่วนเปล่าและชิ้นส่วนเปล่าจะเริ่มต้นได้แตกต่างกันในโก:

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

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

สำหรับทั้งสามชิ้น len และฝาเป็น 0


make([]int, 0)เป็นดีที่สุดเพราะ Jetbrains Goland ไม่บ่นเกี่ยวกับมันเป็น "ไม่จำเป็น" []int{}เช่นเดียวกับในกรณีของ สิ่งนี้มีประโยชน์ในการเขียนการทดสอบหน่วย
Andrzej Rehmann
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.