【go语言】复杂数据类型——切片Slice

1.理解切片Slice

(1)切片是什么?
  • 切片是数组的一个引用,因此是引用类型。
  • slice 通过内部指针和相关属性引用数组片段,以实现变长方案。
  • 切片Slice包含三个部分:
  1. 指向底层数组的指针。
  2. 切片的长度(len):表示切片当前可见的元素个数。
  3. 切片的容量(cap):表示从切片起始位置到底层数组末尾的最大可用元素数量。
(2) 内存布局

Go 的切片在内存中的结构可以用以下类型表示:

type SliceHeader struct {
    Data uintptr // 底层数组的起始地址
    Len  int     // 切片的长度
    Cap  int     // 切片的容量
}
两个切片的声明和初始化
myNum := []int{10,20,30,40,50}
newNum := myNum[1:3]
  • 示意图:

【go语言】复杂数据类型——切片Slice_第1张图片

newNum切片的内存结构:

  • data:20,30
  • len:2
  • cap:4,尽管newNum只包含两个元素,但它的容量是从newNum的起始元素到原数组myNum末尾的元素数量,即[20,30,40,50]这四个元素的空间。因为myNum和newNum共享同一个底层数组,所以newNum的容量受到限制。

2.切片的操作

(1)创建切片

字面量创建:

s := []int{1, 2, 3, 4} // 创建一个长度为 4 的切片

通过 make 函数创建

s := make([]int, length, capacity)

通过数组创建:

arr := [5]int{1, 2, 3, 4, 5}
s := arr[1:4] // 创建一个子切片 [2, 3, 4]

(2)添加切片元素

使用append函数可以向切片追加一个或多个元素。如果追加的元素超出了当前切片的容量,append会分配一个新的底层数组,并将原切片的内容以及新元素复制到新数组中。

超出原 slice.cap 限制,就会重新分配底层数组,即便原数组并未填满。
data := [...]int{0, 1, 2, 3, 4, 10: 0}
s := data[:2:3]//slice内容为data从0到1,容量cap为3
s = append(s, 100, 200) // 一次 append 两个值,超出 s.cap 限制。
fmt.Println(s, data)    // 重新分配底层数组,与原数组无关。
fmt.Println(&s[0], &data[0]) // 比对底层数组起始指针。

输出结果:
[0 1 100 200] [0 1 2 3 4 0 0 0 0 0 0]
0xc4200160f0 0xc420070060

从输出结果可以看出,append 后的 s 重新分配了底层数组,并复制数据。 通常以 2 倍容量重新分配底层数组。

(3)切片拷贝

s1 := []int{1,2,3}
s2 := make([]int,3)
copy(s2,s1) //现在s2是{1,2,3}的拷贝

(4)字符串和切片

string本身是不可变的,因此要修改string中字符。需要如下操作:

str := "Hello world"
s := []byte(str) //中文字符需要用[]rune(str)
s[6] = 'G'
s = s[:8]
str = string(s)
fmt.Println(str)

输出结果:
Hello Go

数组 or 切片 转字符串:

strings.Replace(strings.Trim(fmt.Sprint(array_or_slice), "[]"), " ", ",", -1)

你可能感兴趣的:(golang,golang,学习,开发语言)