Go 语言学习笔记之数组与切片
  F5Pid34CNfer 2024年08月06日 68 0
Go

大家好,我是码农先森。

数组与切片的区别

在 Go 语言中,数组和切片是两种不同的数据结构,它们之间有以下主要区别。

参数长度:
数组(Array):数组的长度是固定的,在创建时就需要指定数组的长度,无法动态改变;只有长度信息,通过 len() 函数获取。
切片(Slice):切片是对数组的一个引用,底层使用的是数组的数据结构,具有动态长度,可以动态增加或减少元素,实现动态扩容;有长度和容量信息,通过 len()cap() 函数可以获取。

参数传递:
数组:在函数间传递数组会进行值拷贝,较大的数组会导致性能开销。
切片:切片是对底层数组的引用,传递切片时只是传递引用,并不会复制整个数组,节省内存和性能。

切片的扩容

当一个切片通过切片操作(如 appendcopyslicing 等)对底层数组进行修改时,如果底层数组容量不足,会创建一个新的底层数组,并将数据复制到新的底层数组中,此时切片会指向新的底层数组。

追加一个元素时,如果切片的容量能够容纳新增元素,即切片的长度小于容量,那么切片的长度会增加 1,容量不变。
但如果超出了当前容量,即切片的长度等于容量,那么会触发切片的扩容,根据倍增规则重新分配底层数组,当原切片的长度大于或等于 1024 时,会以原容量的 1.25 倍作为新容量的基准;通过下面的例子和图解可以更加具体的了解扩容的过程。

// 长度与容量相等
func TestSlice(t *testing.T) {
	var a []int
	fmt.Printf("%v, %v\n", len(a), cap(a)) // 0, 0
	a = append(a, 1)
	a = append(a, 2)
	fmt.Printf("%v, %v\n", len(a), cap(a)) // 2, 2
}

// 当元素的个数超过 1024 长度,则会以 (1280 / 1025) = 1.25 倍进行扩容
func TestSlice(t *testing.T) {
	var a []int
	fmt.Printf("%v, %v\n", len(a), cap(a)) // 0, 0
	i := 1
	for i <= 1025 {
		a = append(a, i)
		i += 1
	}
	fmt.Printf("%v, %v\n", len(a), cap(a)) // 1025, 1280
}

总结

我们了解了数组和切片之间的关系。切片是基于数组的,可变长的,并且操作快。一个切片的容量总是固定的,而且一个切片也只会与某一个底层数组关联。切片的扩容是根据倍增规则重新分配了底层的数组,如果频繁的动态扩容,可能会带来一些性能开销。因此,在对性能有严格要求的场景下,尽量提前估算切片所需的容量,避免频繁的动态扩容。

欢迎关注、分享、点赞、收藏、在看,我是码农先森。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2024年08月06日 0

暂无评论

推荐阅读
  MQD0xJmbEOnQ   2024年08月12日   87   0   0 Go
  UuDQxJhIpKD4   22天前   41   0   0 Go
  pQocAAYIyhh3   6小时前   10   0   0 Go
  yZdUbUDB8h5t   2024年08月07日   36   0   0 Go
F5Pid34CNfer