数组容量被覆盖

huangapple go评论83阅读模式
英文:

Array Cap overwritten

问题

GO大师们!你们能给些建议吗?

  1. 使用make([]int, len, cap),GO是否允许在声明同时进行数组初始化?

    myArray := make([]int, 3, 10){1,2,3}

  2. 在下面的例子中,我发现cap(myArray)len(myArray)的值相同。这背后的原理是什么?

    <ex> myArray := make([]int, 3, 10) myArray = []int{1,2,3} fmt.Println("len:", len(myArray), ", cap:", cap(myArray))

    len: 3, cap: 3

    为什么cap(myArray)的值是3而不是我声明的10?

    我直接初始化了各个元素。而且,它按照我想要的方式工作。

    <ex> myArray := make([]int, 3, 10) myArray[0] = 1 myArray[1] = 2 myArray[2] = 3 fmt.Println("len:", len(myArray), ", cap:", cap(myArray))

    len: 3, cap: 10

英文:

GO MASTERs! could you advise?

  1. with make([]int,len,cap), does GO allow array initialization at the same time to declaration?

    myArray := make([]int, 3, 10){1,2,3}

  2. I see cap(myArray) has changed as same to len(myArray) in the below case. What is fundamental behind?

&lt;ex&gt;
myArray := make([]int, 3, 10)
myArray = []int{1,2,3}
fmt.Println(&quot;len:&quot;len(myArray),&quot;, cap:&quot;,cap(myArray))

> len:3, cap:3

Why cap(myArray) is 3 instead of 10 as I declaration?

I initialized individual element directly. And, it works as I wanted

&lt;ex&gt;
myArray := make([]int, 3, 10)
myArray[0] = 1
myArray[1] = 2
myArray[2] = 3
fmt.Println(&quot;len:&quot;len(myArray),&quot;, cap:&quot;,cap(myArray))

> len:3, cap:10

答案1

得分: 2

我相信你得到这个结果是因为在第一个示例中,你声明了一个长度为3、容量为10的切片。然而,在后面的语句中,你将一个完全不同的切片赋值给了该变量。由于你分配的切片是使用“复合字面量”语法声明/初始化的,并且它只有3个元素,因此它的容量就是初始化时的长度。在你的第二个示例中,你为使用make创建的切片的每个索引赋值,保留了长度和容量属性。

为了更好地解释...在C#、Java或C++中,这就像这样做:

List<string> myStrings = new List<string>();
myStrings.Add("A string");

myStrings = new List<string>();

你可能会猜到,在将新的列表赋给myStrings变量之后,旧的列表就会丢失。所以简单地说,你不仅仅是覆盖了容量,而是覆盖了整个切片。你在赋值中使用的值导致创建了一个容量为3的切片,这就是你得到那个结果的原因。

英文:

I believe you're getting this result because in the first example you declare a slice with a length of 3 and a cap of 10. However, in the following statement you assign a completely different slice to that variable. Since the slice your assigning was declared/initialized using 'composite-literal' syntax and it has only 3 items, that is the capacity it is initialized with. In your second example, you assign values to each index of the slice you created with make, retaining the length and capacity properties.

To try and give more clarification... In C# or Java or C++ this would be like doing something like this;

List&lt;string&gt; myStrings = new List&lt;string&gt;();
myStrings.Add(&quot;A string&quot;);

myStrings = new List&lt;string&gt;();

As you might assume, after assigning a new list to the myStrings variable the old list is lost. So to give the simple answer, you're not just overwriting the cap, you're overwriting the whole slice. The value you have in your assignment that overwrites it, causes a slice to be created with a cap of 3 which is why you get that result.

答案2

得分: 2

这里有几个因素在起作用。我强烈推荐阅读goblog对此的解释:https://blog.golang.org/slices(请滚动到标有"Capacity"的部分)。另外,只是一点点语义上的区别,但实际上这些是切片(slices),而不是数组 数组容量被覆盖

重点是,当你首次声明切片时,它的长度为3,容量为10。这没有问题。但是当你重新声明myArray,并将其设置为[]int{1,2,3}时,问题就出现了。这也是有效的。

问题出现在你期望之前的长度/容量保持不变时;你的切片只是指向内存中某个位置的指针。因此,你现在已经改变了底层指针(参见goblog)。切片的容量和长度也随之改变(变为默认值-再次参见goblog)。如果你添加更多元素,你也可以看到长度/容量的变化:

myArray := make([]int, 3, 10)
fmt.Println("len:", len(myArray), ", cap:", cap(myArray)) // len: 3 cap: 10

myArray := []int{1, 2, 3}
fmt.Println("len:", len(myArray), "cap:", cap(myArray)) // len: 3 cap: 3

myArray = append(myArray, 4)
fmt.Println("len:", len(myArray), "cap:", cap(myArray)) // len: 4 cap: 8;自动增加了容量
英文:

So there's a few things at play here. I would strongly recommend the goblog's explanation of this: https://blog.golang.org/slices (go down to the section labeled Capacity). Also, just a (tiny) bit of semantics, but those are actually slices, not arrays 数组容量被覆盖

To get to the point, when you first declared your slice, you had a len of 3 and a capacity of 10. No problem with that. But then you redeclare myArray, and set it to be []int{1,2,3}. No problems there either, this is valid.

The problem comes when you expected your previous len/cap to remain the same; your slice is just a pointer to some space in memory. So you've now changed your underlying pointer (see the goblog). The capacity and length of the slice is now changed as well (to the default-- again, see the goblog). You can see the same changing of len/cap if you were to add more elements:

myArray := make([]int, 3, 10)
fmt.Println(&quot;len:&quot;len(myArray),&quot;, cap:&quot;,cap(myArray)) // len: 3 cap: 10

myArray := []int{1, 2, 3}
fmt.Println(&quot;len:&quot;, len(myArray), &quot;cap:&quot;, cap(myArray)) // len: 3 cap: 3

myArray = append(myArray, 4)
fmt.Println(&quot;len:&quot;, len(myArray), &quot;cap:&quot;, cap(myArray)) // len: 4 cap: 8; automatically increases the cap

huangapple
  • 本文由 发表于 2016年4月15日 02:27:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/36631130.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定