Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 围棋中的[]int{}和[]int有什么区别?_Go - Fatal编程技术网

Go 围棋中的[]int{}和[]int有什么区别?

Go 围棋中的[]int{}和[]int有什么区别?,go,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:", test

围棋有两种不同的定义,但有什么区别? 我尝试了以下方法:

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)
}
这是输出:

1
test1: []
test2: []

但是为什么test1是nil而另一个不是呢?

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

在:

[]int为变量test1提供类型。该行作为一个整体不提供任何值,因此test1被初始化为[]int类型。其零值为[]intnil,或者非正式地说,仅为nil.1

在:

[]int为括号内的初始值设定项列表提供类型。也就是说,{}是一个:一个开大括号,后跟一个元素列表,在本例中为空,后跟一个闭大括号。行的剩余部分:=和左侧的变量名表示一个。这将为变量test2提供类型[]int和空列表生成的值

在本例中,空列表生成的值是int的空片:一个具有empty2备份存储、长度为零、容量为零的片

这就是为什么test1是nil,而test2不是:test1持有零值,对于任何切片类型,在nil转换为该类型后,该值为nil。同时,test2保存由三部分组成的slice头,该头包含由复合文本创建的零长度支持数组

一个有点草率的nil slice:它意味着slice-of-T类型的值,其实际值是[]Tnil,而不是某个由三部分组成的slice头,通常可以用作相同类型的空长度零slice。特别是,对于i:=range x和x=appendx,newElement都能很好地处理x==nil:它们对待它的方式与对待空切片的方式相同。打印切片的fmt例程也可以这样做

1nil本身是非类型化的。请参阅中第一次提到的nil

2至少在不使用不安全的.Pointer或类似工具的情况下,无法判断Go是否实际为备份阵列分配了任何存储。您在片上执行的任何操作都会给它一些容量,以便您可以将一些值放入内存中的某个位置,这将或可能只是分配一个新的备份数组。不安全的包有一些技巧可以窥视Go运行时,但一般来说,您不需要这样做,也不应该这样做

3相比之下,地图类型并没有发挥得那么好。如果x是非正式的——一个可能为零的切片,而m是一个可能为零的映射,我们可以:

x = append(x, newElem)
但我们不能这样做:

m[key] = newElem
我们必须首先检查m是否为零,如果是,则分配一个空映射:

if m == nil {
    m = make(...) // put in the right type here
}
m[key] = newElem
因此,使用相对普遍:

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

因为x会表现良好,而m不会。关于注释2,有一种受支持的方法可以获取指向片的支持数组的指针:reflect.ValueOfslice.pointer。事实证明,所有分配了零容量的片共享同一个指针。因此,分配容量为零的片并不分配内存。事实上,运行时中的零大小分配使用地址。@ILoverReflection:从技术上讲,它为您提供一个指向支持数组中某个元素的指针。例如,如果该片有backing数组var backing[4]T,但通过重新选择向前调整了2步,则会得到backing[2]的地址,而不是backing[0]。我昨天在试验这个。我们还被告知地址不能超过数组的最后一个元素。如果数组A的大小为1,则可以得到&A[0],但不能得到&A[1]。因此,如果支持阵列的大小为零,我们甚至无法检查&A[0],至少不能正式检查。但是综上所述,如果我们足够不安全,或者仅仅看一下源代码,我们就会发现:是的,当前的实现顺便说一句,我进行实验的原因是想看看是否有一种有效的方法来编写测试:S1和S2片是否可能重叠?答案是有,如果我们被允许不安全,但它没有我们想要的那么有用。
if m == nil {
    m = make(...) // put in the right type here
}
m[key] = newElem
var x []T
m := map[string]T{}