切片 – Slice

数据类型 Liemer_Lius 857℃

1、定义

切片是长度可变的数组,由三部分组成:
指针:指向切片第一个元素指向的数组元素的地址
长度:切片元素的数量
容量:切片开始到结束位置元素的数量

切片的声名:需要指定元素的类型,不需要指定元素的数量(长度),初始值为nil。

var s1 []int
fmt.Printf("Type: %T\n", s1) // Type: []int
fmt.Println(s1 == nil)  // true

切片赋值:

s1 = []int{1, 2, 3, 4} // [1 2 3 4]
s1[0] = 1000  // [1000 2 3 4]

长度、容量:

fmt.Println(len(s1), cap(s1))  // 4 4
s1 := make([]int, 3, 5) // meke的时候指定len, cap, 可以不相同, capacity【容量】不能超过数组的长度
fmt.Println(s1, len(s1), cap(s1)) // [0 0 0] 3 5

append:

s1 = append(s1, 2)
fmt.Println(s1, len(s1), cap(s1)) // [0 0 0 2] 4 5, 长度增加, cap不变
s2 := []int{3, 4}
1 = append(s1, 1, 2, 3)
mt.Println(s1, len(s1), cap(s1)) // [0 0 0 1 2 3] 6 10, 容量自动扩展, 为了提前申请内存
s1 := []int{1, 2}
s2 := []int{2, 3}
s1 = append(s1, s2...) // s2...是对切片的解包
fmt.Println(s1) // [1 2 2 3] 

修改:

s2 := s1[1:3]
fmt.Println(s2, reflect.TypeOf(s2), len(s2), cap(s2))  // [0 0] []int 2 4, 子切片
s2[0] = 200
fmt.Println(s1, s2) // 公用部分修改了都会修改:[0 200 0] [200 0]
s2 = append(s2, 3)
fmt.Println(s1, s2) // 私有部分,只子切片有影响:[0 200 0] [200 0 3]

copy:

s1 := []int{1, 2, 3}
s2 := []int{4, 5}
copy(s2, s1) // s2 < s1, s1的元素copy到s2, 向左
fmt.Println(s2, len(s2), cap(s2)) // [1 2] 2 2, 不会修改s2之前的属性[长度|容量]
copy(s1, s2) // s1 < s2, s2的元素copy到s1, 向左
fmt.Println(s1, len(s1), cap(s1)) // [4 5 3] 3 3

删除: 用子切片实现删除,用copy实现对slice的删除

s1 := []int{1, 2, 3, 4, 5}
copy(s1[2:], s1[3:]) // 把s1的索引从3开始的元素,覆盖索引从2开始的元素
fmt.Println(s1[:len(s1)-1]) // [1 2 4 5], 删除最后一个元素
fmt.Println(append(s1[:2], s1[3:]...)) // 等价于append的操作, s1[3:]...会转换切片为元素

堆栈:先进后出,添加在队尾,移除也在队尾
队列:先进先出,添加在队尾,移除也在队首

// 队列
queue := []int{}
queue = append(queue, 1)
queue = append(queue, 2)
queue = append(queue, 3)
fmt.Println(queue[0])
fmt.Println(queue[1:]) // [2 3]

// 堆栈
stack := []int{}
for i := 1; i <= 3; i++ {
	stack = append(stack, i)
}
fmt.Println(stack[len(stack)-1])
fmt.Println(stack[:len(stack)-1]) // [1 2]

多维切片:

multi_s1 := make([][]int, 0) // 长度为0的空切片
multi_s1 = append(multi_s1, []int{1, 2, 3})
multi_s1 = append(multi_s1, []int{4, 5, 6})
fmt.Printf("%T %v\n", multi_s1, multi_s1) // [][]int [[1 2 3] [4 5 6]]
fmt.Println(multi_s1[0][1]) // 2, 多维切片的元素访问

数组是值类型,array1 = array2,会进行值传递,array2修改不影响array2
切片是引用类型,slice1 = slice2,slice2修改,slice1也会被修改

// Slice
slice01 := []int{1, 2, 3}
slice02 := slice01
slice02[0] = 10
fmt.Println(slice01, slice02) // [10 2 3] [10 2 3]
// Array
array01 := [3]int{1, 2, 3}
array02 := array01
array02[0] = 10
fmt.Println(array01, array02) // [1 2 3] [10 2 3]

排序:

// 数字
slice01 := []int{1, 3, 2, 5, 4}
fmt.Println(slice01) // [1 3 2 5 4], 排序前
sort.Ints(slice01)
fmt.Println(slice01) // [1 2 3 4 5], 排序后
// String
slice01 := []string{"hello", "123", "Liemer", "lius", "gogogo"}
fmt.Println(slice01) // [hello 123 Liemer lius gogogo], 排序前
sort.Strings(slice01)
fmt.Println(slice01) // [123 Liemer gogogo hello lius], 排序后
// Float
slice01 := []float64{1.1, -2.3, 55.2, 3.2, 128.3}
fmt.Println(slice01) // [1.1 -2.3 55.2 3.2 128.3]
sort.Float64s(slice01)
fmt.Println(slice01) // [-2.3 1.1 3.2 55.2 128.3]

转载请注明:liutianfeng.com » 切片 – Slice

喜欢 (2)

评论已关闭。