在Golang中重新切片切片

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

Re-slicing slices in Golang

问题

a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
c len=2 cap=5 [0 0] //为什么c的容量不是2而是5
d len=3 cap=3 [0 0 0]

英文:

I recently picked up the Go language, and now I am confused with the following code:

package main

import "fmt"

func main() {
    a := make([]int, 5)
    printSlice("a", a)
    b := make([]int, 0, 5)
    printSlice("b", b)
    c := b[:2]
    printSlice("c", c)
    d := c[2:5]
    printSlice("d", d)
}

func printSlice(s string, x []int) {
    fmt.Printf("%s len=%d cap=%d %v\n",
	    s, len(x), cap(x), x)
}

And the result:

a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
c len=2 cap=5 [0 0] //why the capacity of c not 2 but 5 instead
d len=3 cap=3 [0 0 0]

答案1

得分: 31

c是从数组b中取出的一个切片。这不是一个拷贝,而只是b的前两个元素的一个窗口。

由于b的容量为5,c可以扩展以占据另外3个位置(实际上它创建了一个新的切片,但是在内存中的位置相同)。

切片的最大容量是底层数组的容量减去切片在数组中的起始位置:

 数组:[0 0 0 0 0 0 0 0 0 0 0 0]
 数组:  <----   容量   --->
 切片:    [0 0 0 0]
 切片:     <---- 容量 ---> 

也许这个程序会更清楚地表明cd只是b的窗口:

func main() {
    b := make([]int, 0, 5)
    c := b[:2]
    d := c[1:5] // 这等同于 d := b[1:5]
    d[0] = 1
    printSlice("c", c)
    printSlice("d", d)
}

输出:

c len=2 cap=5 [0 1] // 修改d也会修改c
d len=4 cap=4 [1 0 0 0]
英文:

c is a slice taken from the array b. This isn't a copy, but just a window over the 2 first elements of b.

As b has a capacity of 5, c could be extended to take the 3 other places (in fact it makes a new slice but over the same place in memory).

The maximal capacity of the slice is the capacity of the underlying array minus the position of the start of the slice in the array :

 array : [0 0 0 0 0 0 0 0 0 0 0 0]
 array :  &lt;----   capacity   ---&gt;
 slice :     [0 0 0 0]
 slice :      &lt;---- capacity ---&gt; 

Maybe this program will make it more clear that c and d are just windows over b :

func main() {
    b := make([]int, 0, 5)
    c := b[:2]
    d := c[1:5] // this is equivalent to d := b[1:5]
    d[0] = 1
    printSlice(&quot;c&quot;, c)
    printSlice(&quot;d&quot;, d)
}

Output :

c len=2 cap=5 [0 1] // modifying d has modified c
d len=4 cap=4 [1 0 0 0] 

答案2

得分: 29

请注意,在go 1.2中(2013年第4季度,现在可用1.2rc1),您可以为切片关联一个独立的容量(而不是从底层数组推断的容量)。

参见“三索引切片”和设计文档

> 切片操作通过描述已创建的数组或切片的连续部分来创建一个新的切片:

var array [10]int
slice := array[2:4]

> 切片的容量是切片可以容纳的最大元素数量,即使在重新切片后也是如此;它反映了底层数组的大小。
在这个例子中,切片变量的容量是8。

(底层数组的容量减去切片在数组中的起始位置)

array : [0 0 0 0 0 0 0 0 0 0]
 array : &lt;---- 容量 ---&gt;
 slice :    [0 0]
 slice :    &lt;-- 容量 --&gt; 8 (10-2)

> Go 1.2添加了新的语法,允许切片操作指定容量和长度
第二个冒号引入了容量值,它必须小于或等于源切片或数组的容量,根据起始位置进行调整

> 例如,

slice = array[2:4:6]

array : [0 0 0 0 0 0 0 0 0 0]
 array : &lt;---- 容量 ---&gt;   10
 slice :    [0 0]
 slice :    &lt;- cap-&gt;           4 (6-2)

> 将切片的长度设置为与之前的例子相同,但其容量现在只有4个元素(6-2)。
使用这个新的切片值无法访问原始数组的最后两个元素

主要的论点是给程序员更多对**append**的控制。

a[i : j : k]

该切片具有:

  • 从0开始的索引
  • 长度等于j - i
  • 容量等于k - i

如果i &lt;= j &lt;= k &lt;= cap(a)不为真,则会引发panic

英文:

Note that in go 1.2 (Q4 2013, 1.2rc1 is available now), you can associate to a slice a capacity of its own (instead of a capacity deduced from the underlying array).

See "Three-index slices", and the design document.

> A slicing operation creates a new slice by describing a contiguous section of an already-created array or slice:

var array [10]int
slice := array[2:4]

> The capacity of the slice is the maximum number of elements that the slice may hold, even after reslicing; it reflects the size of the underlying array.
In this example, the capacity of the slice variable is 8.

(capacity of the underlying array minus the position of the start of the slice in the array)

array : [0 0 0 0 0 0 0 0 0 0]
 array : &lt;---- capacity ---&gt;
 slice :    [0 0]
 slice :    &lt;-- capacity --&gt; 8 (10-2)

> Go 1.2 adds new syntax to allow a slicing operation to specify the capacity as well as the length.
A second colon introduces the capacity value, which must be less than or equal to the capacity of the source slice or array, adjusted for the origin.

> For instance,

slice = array[2:4:6]

array : [0 0 0 0 0 0 0 0 0 0]
 array : &lt;---- capacity ---&gt;   10
 slice :    [0 0]
 slice :    &lt;- cap-&gt;           4 (6-2)

> sets the slice to have the same length as in the earlier example but its capacity is now only 4 elements (6-2).
It is impossible to use this new slice value to access the last two elements of the original array.

The main argument is to give programmers more control over append.

a[i : j : k]

That slice has:

  • indices starting at 0
  • length equals to j - i
  • capacity equals to k - i

The evaluation panics if i &lt;= j &lt;= k &lt;= cap(a) is not true.

huangapple
  • 本文由 发表于 2012年10月7日 20:17:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/12768744.html
匿名

发表评论

匿名网友

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

确定