【问题标题】:Decreasing slice capacity减少切片容量
【发布时间】:2023-03-18 14:07:01
【问题描述】:

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

(我的问题被标记为可能与 this 重复;但是,情况并非如此。我的问题是关于切断切片的前几个元素及其含义。)

为什么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)

    // 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)
}

点击运行按钮后,我们得到以下内容。

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]

【问题讨论】:

标签: go slice


【解决方案1】:

您可以阅读有关切片的更多信息here。但我认为这段话回答了你的问题:

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

因此,如果将切片数据分配给同一变量,则无法恢复切片数据。

容量减少是因为通过删除前 2 个元素,您正在更改指向新切片的指针(切片由指向第一个元素的指针引用)。

切片在内存中的表示方式:

make([]byte, 5)

s = s[2:4]

【讨论】:

  • 谢谢你,亚历克斯。该链接非常有帮助。在我查看链接中上面的图表之前,我并没有完全按照您在此处发布的图表进行操作。 (我不明白蓝色、紫色和粉红色的方块代表切片的内部。)
  • 我已经更新了答案以使其更易于理解。
  • 当我阅读 golang 教程时,我问自己同样的问题。亚历克斯在这里回答得很好,我认为教程作者没有解释为什么会出现这种行为是一个错误。
  • 在我看来,这个答案可能更全面,也可以通过口头解释“结束”切片(例如s[:4])。我从图片中了解到,“开始”切片会改变指针并将 lencap 减少相同的值,而“结束”切片只会减少 len
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-18
    • 1970-01-01
    • 2021-01-18
    • 2021-11-25
    • 2016-08-09
    相关资源
    最近更新 更多