go中的切片Slice

本文详细解析了Go语言中切片的底层实现原理,包括切片的引用特性、长度与容量的区别,如何通过append函数高效添加元素,以及切片在不同情况下的地址变化。同时,介绍了切片的第三个索引如何控制容量,帮助开发者更好地理解和运用切片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、切片是一种引用类型,当引用改变其中元素的值时,其他所有引用都会改变该值

func main(){
	a := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
	s1 := a[3:7]
	s2 := s1[0:5]
	s2[1] = 97
	fmt.Println(string(a))
	fmt.Println(string(s1))
	fmt.Println(string(s2))
}
//运行结果
abcdafghij
dafg
dafgh
//注,s1、s2共享同一个底层数组,但他们可以看到的底层数组的不同部分。
//当两个切片共享同一个底层数组时,若其中一个切片改变了该底层数组的共享部分,另一部分也能感知到。

2、设slice := make([]int, len, cap), 若slice1 := slice[i:j],则slice0的长度为: j - i, 容量为: k - i; 

3、使用len()获取元素个数,使用cap()获取容量;

4、声明切片

(1) var a []dataType
(2) a := make([]dataType, len, cap)

5、创建切片:

  (1)make函数: make([]datatype, len, cap)。该切片底层数组的长度为cap; 

  (2)切片字面量,例:slice := []string{"Red", "Blue", "Green", "Yellow", "Pink"} 。该种方法创建的切片长度和容量由元素的个数确定。使用切片字面量时,可以设置初始长度和容量,例: slice := []string{99: ""}

6、nil和空切片

  (1)nil切片:var slice [] 则slice为nil切片,长度和容量均为0。若函数返回值类型为切片,但函数运行时发生异常,可以返回nil;

  (2)空切片:① slice := make([]int, 0), ② slice := []int{}; 

7、若切片的底层数组没有足够的可用空间,append函数会创建一个新的底层数组,并将被引用的现有的值复制到新数组里,再追加新的值:

func main(){
	slice := []int{10,20,30,40}
	newSlice := append(slice, 50)
	newSlice[1] = 100
	fmt.Println(  slice, len(slice), cap(slice) )
	fmt.Println(  newSlice, len(newSlice), cap(newSlice) )
}
//运行结果:
[10 20 30 40] 4 4
[10 100 30 40 50] 5 8

函数append会智能地处理底层数组的容量增长。在切片容量小于1000时,容量总是成倍地增加。当元素个数超过1000时,每次增加25%; 

8、若多个slice指向相同底层数组,其中一个改变会影响全部;

9、声明Slice:

(1) var a []dataType
(2) a := make([]dataType, len, cap)

10、 给切片添加元素, 使用append函数,第一个参数为要追加元素的切片,后面的参数为追加的元素,当追加元素后,元素个数不超过容量时,地址不变,超过后地址改变

func main(){
	s1 := make([]int, 3, 6)
	fmt.Printf("%v, %p\n", s1, s1)
	s1 = append(s1, 2,3,4)
	fmt.Printf("%v, %p\n", s1, s1)
	s1 = append(s1, 5,6,7)
	fmt.Printf("%v, %p\n", s1, s1)
}
//运行结果:
[0 0 0], 0xc00008a030
[0 0 0 2 3 4], 0xc00008a030
[0 0 0 2 3 4 5 6 7], 0xc000050060

11、切片的第三个索引

    切片的第三个索引是用来控制切片的容量

    设 newSlice = slice[i:j:k],则newSlice的

        长度:j - i

        容量:k - i

func main(){
	source := []string{ "Apple", "Orange", "Plum", "Banana", "Grape" }
	slice := source[2:3:4]
	fmt.Println(  source, len(source), cap(source) )
	fmt.Println(  slice, len(slice), cap(slice) )
}
// 运行结果:
[Apple Orange Plum Banana Grape] 5 5
[Plum] 1 2

允许限制新切片的容量,为底层数组提供了一定的保护,可以更好地控制追加操作。可强制让新切片的第一个append操作创建新的底层数组,与原有的底层数组分离,可以安全地进行后续修改

func main(){
	source := []string{ "Apple", "Orange", "Plum", "Banana", "Grape" }
	slice := source[2:3:3]
	slice = append(slice, "Wiki")
	slice2 := source[3:4:5]
	slice2 = append(slice2, "Egg")
	fmt.Println(  source, len(source), cap(source) )
	fmt.Println(  slice, len(slice), cap(slice) )
	fmt.Println(  slice2, len(slice2), cap(slice2) )
}
//运行结果:
[Apple Orange Plum Banana Egg] 5 5
[Plum Wiki] 2 2
[Banana Egg] 2 2

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值