目录
问题内容
解决方法
可观察的行为
指针。
首页 后端开发 Golang Go 语言中 nil 切片、非 nil 切片、空切片

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

Feb 08, 2024 pm 09:18 PM
go语言

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

php小编小新为你带来了关于Go语言中的切片类型的介绍。在Go语言中,切片有三种状态:nil切片、非nil切片和空切片。这三种切片状态在使用时具有不同的含义和特点。了解这些切片类型的区别,将有助于我们更好地理解和使用Go语言中的切片功能。接下来,让我们一起来探索这三种切片类型的具体特点和用法。

问题内容

我是 Go 编程的新手。我在Go编程书中读到,切片由三部分组成:指向数组的指针、长度和容量。

我对以下内容感到困惑:

  • nil 切片(切片没有指向的底层数组,len = 0,cap=0)
  • 仅 len = 0、cap = 0 的非零切片
  • 空切片。

谁能告诉我 nil 和空切片是否是同一件事? 如果两者不同,那么请告诉我这两者有什么区别?如何测试切片是否为空?另外,指针在长度和容量为零的非零切片中保存什么值?

解决方法

可观察的行为

nil 和空切片(容量为 0)并不相同,但它们的可观察行为是相同的(几乎始终)。我的意思是:

  • 您可以将它们传递给内置 len()cap() 函数
  • 您可以 for range 覆盖它们(将是 0 次迭代)
  • 您可以对它们进行切片(只要不违反规范:切片表达式中概述的限制;因此结果也将是一个空切片)
  • 由于它们的长度为 0,因此您无法更改其内容(附加值会创建新的切片值)

查看这个简单的示例(一个 nil 切片和 2 个非 nil 切片和 2 个非

空切片):

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 {}
登录后复制
输出(在 Go Playground

上尝试一下):

s1 0 0 true [] true
s2 0 0 false [] false
s3 0 0 false [] false
登录后复制
nil 切片进行切片会生成 nil 切片,对非 nil 切片进行切片会生成非 nil(请注意,对

切片进行切片会生成

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

除了例外之外,您只能通过将切片值与预声明的标识符

进行比较来区分,它们在其他方面的行为都是相同的。 但请注意,许多软件包确实会将切片与 进行比较,并且可能会基于此进行不同的操作(例如 encoding/ jsonfmt 包)。nil 切片转换为数组指针将生成非 nil 指针,将 nil 切片转换为数组指针将生成 nil

唯一的区别是

将切片转换为数组指针0 进行比较:len(s) == 0。无论它是 nil 切片还是非 nil(已添加到

Go 1.17

中的语言)。将非 切片转换为数组指针将生成非 指针,将

切片转换为数组指针将生成

指针。

要判断切片是否为空,只需将其长度与 0 进行比较:len(s) == 0。无论它是 切片还是非 reflect.SliceHeader 切片,它是否具有正容量也并不重要;如果没有元素,则为空。

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

打印(在

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

Empty: true , but capacity: 100
登录后复制

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

切片值由

中定义的结构表示:

type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}
登录后复制
🎜对于 🎜 切片,该结构将具有其零值,即其所有字段都将为零值,即:0。🎜 🎜如果非 🎜 切片的容量和长度等于 0LenCap 字段,则很可能是 0,但 Data 指针可能不是。它不会,这就是它与 🎜 切片的区别。它将指向一个零大小的底层数组。🎜 🎜请注意,Go 规范允许大小为 0 的不同类型的值具有相同的内存地址。 🎜规范:系统注意事项:大小和对齐保证:🎜🎜

让我们检查一下。为此,我们调用 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 大小的内存值

以上是Go 语言中 nil 切片、非 nil 切片、空切片的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Go语言中用于浮点数运算的库有哪些? Go语言中用于浮点数运算的库有哪些? Apr 02, 2025 pm 02:06 PM

Go语言中用于浮点数运算的库介绍在Go语言(也称为Golang)中,进行浮点数的加减乘除运算时,如何确保精度是�...

Go的爬虫Colly中Queue线程的问题是什么? Go的爬虫Colly中Queue线程的问题是什么? Apr 02, 2025 pm 02:09 PM

Go爬虫Colly中的Queue线程问题探讨在使用Go语言的Colly爬虫库时,开发者常常会遇到关于线程和请求队列的问题。�...

Go语言中哪些库是由大公司开发或知名的开源项目提供的? Go语言中哪些库是由大公司开发或知名的开源项目提供的? Apr 02, 2025 pm 04:12 PM

Go语言中哪些库是大公司开发或知名开源项目?在使用Go语言进行编程时,开发者常常会遇到一些常见的需求,�...

Go语言中`var`和`type`关键字定义结构体的区别是什么? Go语言中`var`和`type`关键字定义结构体的区别是什么? Apr 02, 2025 pm 12:57 PM

Go语言中结构体定义的两种方式:var与type关键字的差异Go语言在定义结构体时,经常会看到两种不同的写法:一�...

在Go语言中使用Redis Stream实现消息队列时,如何解决user_id类型转换问题? 在Go语言中使用Redis Stream实现消息队列时,如何解决user_id类型转换问题? Apr 02, 2025 pm 04:54 PM

Go语言中使用RedisStream实现消息队列时类型转换问题在使用Go语言与Redis...

在 Go 语言中,为什么使用 Println 和 string() 函数打印字符串会出现不同的效果? 在 Go 语言中,为什么使用 Println 和 string() 函数打印字符串会出现不同的效果? Apr 02, 2025 pm 02:03 PM

Go语言中字符串打印的区别:使用Println与string()函数的效果差异在Go...

在使用Go语言和viper库时,为什么传递指针的指针是必要的? 在使用Go语言和viper库时,为什么传递指针的指针是必要的? Apr 02, 2025 pm 04:00 PM

Go指针语法及viper库使用中的寻址问题在使用Go语言进行编程时,理解指针的语法和使用方法至关重要,尤其是在...

为什么Go语言中使用for range遍历slice并存入map时,所有值会变成最后一个元素? 为什么Go语言中使用for range遍历slice并存入map时,所有值会变成最后一个元素? Apr 02, 2025 pm 04:09 PM

为什么Go语言中的map迭代会导致所有值变成最后一个元素?在Go语言中,面对一些面试题时,经常会遇到关于map�...

See all articles