Go语言核心36讲笔记05--数据和切片


1.数组与切片的区别与联系

  • 数组的值的长度是固定的,而切片的值是可变长的
  • 切片的长度可以自动地随着其中元素数量的增长而增长,但不会随着元 素数量的减少而减少
  • 切片是引用类型,数组是值类型
  • 切片的容量表示其底层数组的长度
  • 切片的长度表示可以连续获取其底层数组中元素的数量

2.怎样估算切片容量的增长?

  • 当一个切片无法容纳更多的元素时就会扩容,但是并不会改变原来的切片,而是会生成一个容量更大的切片,然后将原有的元素和新增的元素拷贝至新切片
  • 一般情况下新切片的容量是原切片容量的2倍
  • 当原切片的长度(以下简称原长度)大于或等于1024时,Go 语言将会以原容量的1.25 倍作为新容量的基准,新容量基准会被调整(不断地与1.25相乘),直到结果不小于原长度与要追加的元素数量之和
  • 如果一次追加的元素过多,以至于使新长度比原容量的 2 倍还要大,那么新容量就 会以新长度为基准
package main

import "fmt"

func main() {
	s6 := make([]int, 0)
	fmt.Printf("The capacity of s6: %d\n", cap(s6))
	for i := 1; i <= 5; i++ {
		s6 = append(s6, i)
		fmt.Printf("s6(%d): len: %d, cap: %d\n", i, len(s6), cap(s6))
	}
	fmt.Println("-----------------------------------------------------------------")

	s7 := make([]int, 1024)
	fmt.Printf("The capacity of s7: %d\n", cap(s7))
	s7e1 := append(s7, make([]int, 200)...)
	fmt.Printf("s7e1: len: %d, cap: %d\n", len(s7e1), cap(s7e1))
	s7e2 := append(s7, make([]int, 400)...)
	fmt.Printf("s7e2: len: %d, cap: %d\n", len(s7e2), cap(s7e2))
	s7e3 := append(s7, make([]int, 600)...)
	fmt.Printf("s7e3: len: %d, cap: %d\n", len(s7e3), cap(s7e3))
	fmt.Println("-----------------------------------------------------------------")

	s8 := make([]int, 10)
	fmt.Printf("The capacity of s8: %d\n", cap(s8))
	s8a := append(s8, make([]int, 11)...)
	fmt.Printf("s8a: len: %d, cap: %d\n", len(s8a), cap(s8a))
	s8b := append(s8a, make([]int, 23)...)
	fmt.Printf("s8b: len: %d, cap: %d\n", len(s8b), cap(s8b))
	s8c := append(s8b, make([]int, 45)...)
	fmt.Printf("s8c: len: %d, cap: %d\n", len(s8c), cap(s8c))
}

3.切片的底层数组什么时候会被替换?

  • 一个切片的底层数组永远不会被替换。虽然在扩容的时候 Go 语言一定会生成新的底层数组,但是它也同时生成了新的切片。它是把新的切片作为了新底层数组的窗口,而没有对原切片及其底层数组做任何改动
  • 在无需扩容时,append函数返回的是指向原底层数组的新切片,而在需要扩容时, append函数返回的是指向新底层数组的新切片
package main

import "fmt"

func main() {
	a1 := [7]int{1, 2, 3, 4, 5, 6, 7}
	fmt.Printf("a1: %v (len: %d, cap: %d)\n",
		a1, len(a1), cap(a1))
	s9 := a1[1:4]
	//s9[0] = 1
	fmt.Printf("s9: %v (len: %d, cap: %d)\n",
		s9, len(s9), cap(s9))
	for i := 1; i <= 5; i++ {
		s9 = append(s9, i)
		fmt.Printf("s9(%d): %v (len: %d, cap: %d)\n",
			i, s9, len(s9), cap(s9))
	}
	fmt.Printf("a1: %v (len: %d, cap: %d)\n",
		a1, len(a1), cap(a1))
	fmt.Println()

}

4.思考题

(1)如果有多个切片指向了同一个底层数组,那么你认为应该注意些什么?
答:对切片的修改都会反映在底层数组中
(2)怎样沿用“扩容”的思想对切片进行“缩容”?
答:生成新切片,缩小窗口大小

最后本节涉及代码可以参考:demo GitHub地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值