Rumah >pembangunan bahagian belakang >Golang >hirisan nil, hirisan bukan nol, hirisan kosong dalam bahasa Go

hirisan nil, hirisan bukan nol, hirisan kosong dalam bahasa Go

WBOY
WBOYke hadapan
2024-02-08 21:18:081282semak imbas

Go 语言中 nil 切片、非 nil 切片、空切片

Editor PHP Xiaoxin membawakan anda pengenalan kepada jenis kepingan dalam bahasa Go. Dalam bahasa Go, hirisan mempunyai tiga keadaan: hirisan nil, hirisan bukan nol dan hirisan kosong. Ketiga-tiga keadaan penghirisan ini mempunyai maksud dan ciri yang berbeza apabila digunakan. Memahami perbezaan antara jenis hirisan ini akan membantu kami lebih memahami dan menggunakan fungsi hirisan dalam bahasa Go. Seterusnya, mari kita terokai ciri khusus dan kegunaan ketiga-tiga jenis kepingan ini.

Kandungan soalan

Saya baru dalam pengaturcaraan Go. Saya membaca dalam buku pengaturcaraan Go bahawa kepingan terdiri daripada tiga bahagian: penunjuk kepada tatasusunan, panjang dan kapasiti.

Saya keliru tentang perkara berikut:

  • hirisan nol (hirisan tidak mempunyai tatasusunan asas yang ditunjuk, len = 0, topi=0)
  • Hanya kepingan bukan sifar dengan len = 0, topi = 0
  • Hirisan kosong.

Boleh sesiapa beritahu saya jika tiada dan kepingan kosong adalah perkara yang sama? Jika kedua-duanya berbeza, sila beritahu saya apa perbezaan antara kedua-duanya? Bagaimana untuk menguji sama ada sekeping kosong? Juga, apakah nilai yang dipegang oleh penunjuk dalam kepingan bukan sifar dengan panjang dan kapasiti sifar?

Penyelesaian

Tingkah laku yang boleh diperhatikan

nil tidak sama dengan kepingan kosong (kapasiti 0), tetapi tingkah laku yang boleh diperhatikan adalah sama (hampir selalu). Apa yang saya maksudkan ialah:

  • Anda boleh menghantarnya ke fungsi len()cap() terbina dalam
  • Anda boleh for range mengatasinya (akan menjadi 0 lelaran)
  • Anda boleh menghirisnya (asalkan ia tidak melanggar sekatan yang digariskan dalam Spesifikasi: Ungkapan Menghiris ; jadi hasilnya juga akan menjadi kepingan kosong)
  • Memandangkan mereka mempunyai panjang 0, anda tidak boleh menukar kandungannya (menambah nilai menghasilkan nilai kepingan baharu)

Lihat contoh mudah ini (satu nil 切片和 2 个非 nil keping dan 2 bukan

keping kosong):

var s1 []int         // nil slice
s2 := []int{}        // non-nil, empty slice
s3 := make([]int, 0) // non-nil, empty slice

fmt.Println("s1", len(s1), cap(s1), s1 == nil, s1[:], s1[:] == nil)
fmt.Println("s2", len(s2), cap(s2), s2 == nil, s2[:], s2[:] == nil)
fmt.Println("s3", len(s3), cap(s3), s3 == nil, s3[:], s3[:] == nil)

for range s1 {}
for range s2 {}
for range s3 {}
Output (cuba di Go Playground

):

s1 0 0 true [] true
s2 0 0 false [] false
s3 0 0 false [] false
nil 切片进行切片会生成 nil 切片,对非 nil 切片进行切片会生成非 nil (Perhatikan bahawa menghiris sekeping

menghasilkan sekeping

, dan menghiris sekeping bukan nil 进行比较来区分,它们在其他方面的行为都是相同的。 但请注意,许多软件包确实会将切片与 nil 进行比较,并且可能会基于此进行不同的操作(例如 encoding/ jsonfmt menghasilkan sekeping bukan .)

Dengan pengecualian bahawa anda hanya boleh membezakannya dengan membandingkan nilai hirisan dengan pengecam yang diisytiharkan sebelumnya

, mereka sebaliknya berkelakuan sama. Tetapi ambil perhatian bahawa banyak pakej membandingkan kepingan dengan dan mungkin melakukan perkara secara berbeza berdasarkan itu (cth. pengekodan/ json dan fmt pakej). nil 切片转换为数组指针将生成非 nil 指针,将 nil 切片转换为数组指针将生成 nil

Satu-satunya perbezaan ialah

menukar kepingan kepada penunjuk tatasusunan0 进行比较:len(s) == 0。无论它是 nil 切片还是非 nil (ditambah pada bahasa dalam

Go 1.17

). Menukar hirisan bukan kepada penunjuk tatasusunan akan menghasilkan penuding bukan , dan menukar hirisan

kepada penuding tatasusunan akan menghasilkan penuding

.

Untuk mengetahui sama ada kepingan kosong, cuma bandingkan panjangnya dengan 0: len(s) == 0. Sama ada hirisan atau hirisan bukan reflect.SliceHeader, tidak kira sama ada ia mempunyai kapasiti positif jika ia tidak mempunyai unsur, ia kosong.

s := make([]int, 0, 100)
fmt.Println("Empty:", len(s) == 0, ", but capacity:", cap(s))

Cetak (cuba di

Go Playgroundnil 切片,该结构将具有其零值,即其所有字段都将为零值,即:0):

Empty: true , but capacity: 100

Lapisan bawahnil 切片的容量和长度等于 0LenCap 字段,则很可能是 0,但 Data 指针可能不是。它不会,这就是它与 nil

Nilai kepingan diwakili oleh struktur yang ditakrifkan dalam

:

type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}
🎜Untuk kepingan 🎜, struktur akan mempunyai nilai sifarnya, iaitu semua medannya akan mempunyai nilai sifar, iaitu: 0. 🎜 🎜Jika kapasiti dan panjang kepingan bukan 🎜 adalah sama dengan medan 0, Len dan Cap, maka kemungkinan besar 0 , tetapi penunjuk Data mungkin tidak. Iatidak, begitulah bezanya dengan 🎜 hirisan. Ia akan menunjuk kepada tatasusunan asas bersaiz sifar. 🎜 🎜Perhatikan bahawa spesifikasi Go membolehkan nilai jenis berbeza dengan saiz 0 mempunyai alamat memori yang sama. 🎜Spesifikasi: Nota Sistem: Saiz dan Jaminan Penjajaran: 🎜🎜

让我们检查一下。为此,我们调用 unsafe 包的帮助,并“获取” reflect.SliceHeader 结构“视图” “我们的切片值:

var s1 []int
s2 := []int{}
s3 := make([]int, 0)

fmt.Printf("s1 (addr: %p): %+8v\n",
    &s1, *(*reflect.SliceHeader)(unsafe.Pointer(&s1)))
fmt.Printf("s2 (addr: %p): %+8v\n",
    &s2, *(*reflect.SliceHeader)(unsafe.Pointer(&s2)))
fmt.Printf("s3 (addr: %p): %+8v\n",
    &s3, *(*reflect.SliceHeader)(unsafe.Pointer(&s3)))

输出(在 Go Playground 上尝试一下):

s1 (addr: 0x1040a130): {Data:       0 Len:       0 Cap:       0}
s2 (addr: 0x1040a140): {Data: 1535812 Len:       0 Cap:       0}
s3 (addr: 0x1040a150): {Data: 1535812 Len:       0 Cap:       0}

我们看到了什么?

  • 所有切片(切片头)都有不同的内存地址
  • nil 切片具有 0 数据指针
  • s2s3 切片确实具有相同的数据指针,共享/指向相同的 0 大小的内存值

Atas ialah kandungan terperinci hirisan nil, hirisan bukan nol, hirisan kosong dalam bahasa Go. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam