为了账号安全,请及时绑定邮箱和手机立即绑定

go中的[]int{}和[]int有什么区别?

go中的[]int{}和[]int有什么区别?

Go
萧十郎 2023-08-14 15:07:22
go里有两种不同的定义,但是有什么区别呢?我已经尝试过以下方法:func main() {    var test1 []int    test2 := []int{}    if test1 == nil {        fmt.Println(1)    }    if test2 == nil {        fmt.Println(2)    }    fmt.Println("test1:", test1)    fmt.Println("test2:", test2)}这是输出:1test1: []test2: []但为什么 test1 是 nil 而另一个不是呢?
查看完整描述

2 回答

?
元芳怎么了

TA贡献1798条经验 获得超7个赞

就其本身而言,是 的类型切片的[]int拼写。int

在:

var test1 []int

提供[]int变量的类型test1。该行作为一个整体不提供任何值,因此test1被初始化为type 的零值[]int。它的零值是[]int(nil),或者非正式地,就是 nil 。1

在:

test2 := []int{}

提供[]int大括号括起来的初始值设定项列表的类型。也就是说,{}是一个复合文字:一个左大括号,后跟一个元素列表(在本例中为空),后跟一个右大括号。该行的其余部分(:=左侧的 和变量名称)表示一个简短的变量声明。这为变量提供了类型test2,以及空列表生成的值。 []int

在这种情况下,空列表生成的值是 的一个空切片int: 1 具有空的2后备存储,长度为零,容量为零。

这就是为什么test1is nil 但test2不是:test1保存零值,对于任何切片类型来说,都是nilnil无论如何转换为该类型之后)。同时test2保存由三部分组成的切片头,该头覆盖由复合文字创建的零长度支持数组。

一个 nil 切片——这是一个有点草率的措辞:它意味着一个 slice-of 类型的值,T其实际值[]T(nil)而不是某些由三部分组成的切片头——通常可以用作相同类型。特别是,for i := range x两者x = append(x, newElement)都处理得x == nil“很好”:它们对待它的方式与对待空切片的方式相同。打印切片的例程fmt也执行此操作。3


1nil本身是无类型的nil请参阅 Go 规范中变量部分下第一次提到的。

2至少在没有使用或类似的情况下,不可能判断unsafe.PointerGo 是否实际为后备数组分配了任何存储空间。您对切片执行的任何操作都可以为其提供一些容量,以便您可以将一些值放入内存中的某个位置,都将或可能只是分配一个新的后备数组。该包有一些unsafe用于查看 Go 运行时的技巧,但一般来说,您不需要也不应该这样做。

3相比之下,map类型的表现就没那么好了。如果x是(非正式地说)一个可能为零的切片,并且m是一个可能为零的映射,我们可以这样做:

x = append(x, newElem)

但我们不能这样做:

m[key] = newElem

我们必须首先检查是否m为 nil,如果是,则分配一个空映射:

if m == nil {
    m = make(...) // put in the right type here
    }
m[key] = newElem

所以比较常用的是:

var x []T
m := map[string]T{}

就在彼此旁边,因为x会表现得很好,也m不会表现得很好。


查看完整回答
反对 回复 2023-08-14
?
一只名叫tom的猫

TA贡献1906条经验 获得超2个赞

这是 nil 和空切片之间的区别。在golang中,如果你声明一个没有值的变量,它的值将成为该变量类型的零值。数组的零值为 nil。不是空切片。可以使用 make 函数或 Shorty 用于 test2 的第二种方法来生成空切片



查看完整回答
反对 回复 2023-08-14
  • 2 回答
  • 0 关注
  • 162 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信