减少切片容量

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

Decreasing slice capacity

问题

我的问题是关于切片长度和容量的。我在这里学习Go语言:https://tour.golang.org/moretypes/11。

(我的问题被标记为可能是这个问题的重复;然而,这并不是事实。我的问题特别涉及到切片的前几个元素被截断以及这样做的影响。)

为什么 s = s[2:] 这一行会减少容量,而 s = s[:4]s = s[:0] 不会呢?我唯一看到的区别是在 s = s[2:] 中冒号前面有一个数字,而在其他两行中冒号后面有一个数字。

有没有办法恢复被 s = s[2:] 截断的前两个元素?

package main

import "fmt"

func main() {
    s := []int{2, 3, 5, 7, 11, 13}
    printSlice(s)

    // 将切片切割为零长度。
    s = s[:0]
    printSlice(s)

    // 扩展切片的长度。
    s = s[:4]
    printSlice(s)

    // 删除前两个值。
    s = s[2:]
    printSlice(s)
}

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

点击运行按钮后,我们得到以下结果。

len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]
英文:

My question is about slice length and capacity. I'm learning about Go here: https://tour.golang.org/moretypes/11.

(My question was marked as a possible duplicate of this; however, this is not the case. My question is specifically about the cutting off the first few elements of a slice and the implications of that.)

Why does the line s = s[2:] decrease the capacity when s = s[:4] and s = s[:0] do not? The only difference I see is that there is a number before the colon in s = s[2:] while there is a number after the colon in the other two lines.

Is there any way to recover the first two elements that we cut off with s = s[2:]?

package main

import "fmt"

func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	printSlice(s)

	// Slice the slice to give it zero length.
	s = s[:0]
	printSlice(s)

	// Extend its length.
	s = s[:4]
	printSlice(s)

	// Drop its first two values.
	s = s[2:]
	printSlice(s)
}

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

After clicking the Run button, we get the following.

len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]

答案1

得分: 30

你可以在这里阅读更多关于切片的内容:链接。但我认为这段话回答了你的问题:

“切片不会复制切片的数据。它创建一个指向原始数组的新切片值。这使得切片操作与操作数组索引一样高效。因此,修改重新切片的元素(而不是切片本身)会修改原始切片的元素。”

因此,如果你将切片赋值给同一个变量,你将无法恢复切片数据。

容量减少是因为通过删除前两个元素,你改变了指向新切片的指针(切片是通过指向第一个元素的指针引用的)。

切片在内存中的表示方式如下:
减少切片容量

make([]byte, 5)

减少切片容量

s = s[2:4]

减少切片容量

英文:

You can read more about slices here. But I think this passage answers your question:

> Slicing does not copy the slice's data. It creates a new slice value that points to the original array. This makes slice operations as efficient as manipulating array indices. Therefore, modifying the elements (not the slice itself) of a re-slice modifies the elements of the original slice.

So you cannot recover the slice data if you are assigning it to the same variable.

The capacity decrease is because by dropping the first 2 elements you are changing the pointer to the new slice (slices are referenced by the pointer to the first element).

How slices are represented in the memory:
减少切片容量

make([]byte, 5)

减少切片容量

s = s[2:4]

减少切片容量

答案2

得分: 1

你可以使用完整的切片表达式:

package main

func main() {
   s := []int{2, 3, 5, 7, 11, 13}
   { // 示例 1
      t := s[:0]
      println(cap(t) == 6)
   }
   { // 示例 2
      t := s[:0:0]
      println(cap(t) == 0)
   }
}

https://golang.org/ref/spec#Slice_expressions

英文:

You can use a full slice expression:

package main

func main() {
   s := []int{2, 3, 5, 7, 11, 13}
   { // example 1
      t := s[:0]
      println(cap(t) == 6)
   }
   { // example 2
      t := s[:0:0]
      println(cap(t) == 0)
   }
}

https://golang.org/ref/spec#Slice_expressions

答案3

得分: 0

slices.Clip"golang.org/x/exp/slices" 中的一个函数,它可以通过完整切片表达式来减少切片的容量。

> Clip 函数会移除切片中未使用的容量,并返回 s[:len(s):len(s)]。

func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	printSlice(s)

	s = s[:4]
	printSlice(s)

	s = slices.Clip(s)
	printSlice(s)

}

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

输出结果为:

len=6 cap=6 [2 3 5 7 11 13]
len=4 cap=6 [2 3 5 7]
len=4 cap=4 [2 3 5 7]

Playground

英文:

The slices.Clip of "golang.org/x/exp/slices" could reduce the capacity of slice through Full slice expressions.

> Clip removes unused capacity from the slice, returning s[:len(s):len(s)].

func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	printSlice(s)

	s = s[:4]
	printSlice(s)

	s = slices.Clip(s)
	printSlice(s)

}

func printSlice(s []int) {
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
len=6 cap=6 [2 3 5 7 11 13]
len=4 cap=6 [2 3 5 7]
len=4 cap=4 [2 3 5 7]

Playground

huangapple
  • 本文由 发表于 2017年4月8日 21:04:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/43294449.html
匿名

发表评论

匿名网友

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

确定