Cách chính xác để khởi tạo lát trống


227

Để khai báo một lát trống, với kích thước không cố định, tốt hơn là làm:

mySlice1 := make([]int, 0)

hoặc là:

mySlice2 := []int{}

Chỉ cần tự hỏi cái nào là cách chính xác.


2
Bạn nói "kích thước không cố định", nhưng lát không bao giờ có kích thước cố định. Trừ khi bạn có nghĩa là với năng lực bằng không. Lưu ý, nếu bạn có ý tưởng / đoán / gợi ý về khả năng bạn có thể cần thì sử dụng phiên bản ba đối số là tốt. Ví dụ: để tạo một lát khóa bản đồ:keys := make([]int, 0, len(m)); for k, v := range m { keys := append(keys,k) }
Dave C

Câu trả lời:


272

Hai phương án bạn đưa ra giống hệt nhau về mặt ngữ nghĩa, nhưng việc sử dụng make([]int, 0)sẽ dẫn đến một cuộc gọi nội bộ đến runtime.makeslice (Go 1.14).

Bạn cũng có tùy chọn để lại nó với một nilgiá trị:

var myslice []int

Như được viết trong blog Golang.org :

một lát cắt không có chức năng tương đương với một lát cắt có độ dài bằng không, mặc dù nó chỉ ra không có gì. Nó có độ dài bằng 0 và có thể được thêm vào, với sự phân bổ.

nilTuy nhiên, một lát sẽ json.Marshal()thành "null"một lát trống"[]" , như được chỉ ra bởi @farwayer.

Không có tùy chọn nào ở trên sẽ gây ra bất kỳ sự phân bổ nào, như được chỉ ra bởi @ArmanOrdookhani.


4
Cũng đề cập trên wiki github.com/golang/go/wiki/
Kẻ

106
Hãy cẩn thận: json.Marshal()sẽ trở lại nullcho var myslice []int[]cho lát khởi tạomyslice := []int{}
farwayer

10
Cũng phải cẩn thận: reflect.DeepEquallàm cho một sự phân biệt giữa lát bằng không và dừng lát phi nil: a := []int{}, var b []int,reflect.DeepEqual(a, b) // returns false
asgaines

1
Tại sao bạn nghĩ rằng nó sẽ làm một phân bổ? Cap là 0 nên không có gì được phân bổ. Tất cả các con trỏ đến độ dài bằng không chỉ vào cùng một vị trí trong bộ nhớ: play.golang.org/p/MPOKKl_sYvw
Arman Ordookhani

1
@ArmanOrdookhani Bạn nói đúng. Tôi đã thử nó, và tôi cũng phát hiện ra rằng tôi đã sai với giả định của mình về các hướng dẫn lắp ráp giống hệt nhau. Đã sửa!
ANisus

65

Chúng là tương đương. Xem mã này:

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

Đầu ra:

mySlice1 0
mySlice2 0

Cả hai lát có 0khả năng ngụ ý cả hai lát có0 độ dài (không thể lớn hơn dung lượng) ngụ ý cả hai lát không có phần tử. Điều này có nghĩa là 2 lát giống hệt nhau ở mọi khía cạnh.

Xem các câu hỏi tương tự:

Điểm có lát cắt không và lát trống trong golang là gì?

nil lát so với lát không nil và lát trống trong ngôn ngữ Go


46

Là một bổ sung cho câu trả lời của @ANisus ...

dưới đây là một số thông tin từ cuốn sách "Hành động" , mà tôi nghĩ là đáng nói:

Sự khác biệt giữa nil& emptylát

Nếu chúng ta nghĩ về một lát như thế này:

[pointer] [length] [capacity]

sau đó:

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

nil lát

Chúng rất hữu ích khi bạn muốn biểu diễn một lát cắt không tồn tại, chẳng hạn như khi một ngoại lệ xảy ra trong một hàm trả về một lát.

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

lát trống

Các lát trống hữu ích khi bạn muốn biểu diễn một bộ sưu tập trống, chẳng hạn như khi truy vấn cơ sở dữ liệu trả về kết quả bằng không.

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

Cho dù bạn đang sử dụng một lát nil hoặc một lát rỗng, được xây dựng trong chức năng append, lencapcông việc tương tự.


Ví dụ về sân chơi :

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))

}

in:

true 0 0
false 0 0

Chúng ta có thể lấy địa chỉ của lát trống trong một bước bằng cách sử dụng makekhông?
Simin Jie

Nếu chúng ta xem chữ ký hàm , makedường như không trả về địa chỉ. Tôi tin rằng bạn không thể làm điều đó trong một bước.
tgogos

13

Lát rỗng và lát cắt không được khởi tạo khác nhau trong Go:

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

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

Đối với cả ba lát, len và nắp là 0.


make([]int, 0)là tốt nhất vì Jetbrains GoLand không phàn nàn về việc nó "không cần thiết" như trong trường hợp []int{}. Điều này rất hữu ích trong việc viết bài kiểm tra đơn vị.
Andrzej Rehmann
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.