go从0到1项目实战体系六:slice切片

1. slice:

. 基础:
   a. 切片是指向数组的一个引用,因此切片是引用类型.
   b. 切片的长度可以改变.因此,切片是一个可变的数组.
   c. 切片遍历方式和数组一样,可以用len()求长度.. 定义:
   var 变量名 []类型         // 与数组的区别是没有写长度
   a. var arr []string. len是长度、cap是容量:
   a. cap表示slice最大的容量.
   b. 大小关系:
      0 <= len(slice) <= (array:slice引用的数组).

2. 通过数组创建切片:

var slice []int = arr[start:end]        // 包含数组的start到end之间的元素(但不包含end)
var slice []int = arr[0:end]            // 简写var slice []int = arr[:end]
var slice []int = arr[start:len(arr)]   // 从start到末尾的所有元素,简写var slice []int = arr[start:]
var slice []int = arr[0, len(arr)]      // 数组的所有元素,简写var slice []int = arr[:]
slice = slice[:len(slice)-1]            // 切片最后一个元素去掉

(1). 数组创建切片的内存布局:

. 如上图数据结构:
   [ptr指针地址]  [len长度]  [cap]
   类似:
   type slice struct {
      ptr *[5]int     =>  指向一个数组
      len
      cap
   }. 验证最下面切片的ptr地址是指向数组的第1个元素的地址:
   var a = [5]int{1, 2, 3, 4, 5}
	b := a[1:5]
	fmt.Println(b)                     // [2 3 4 5]
	fmt.Printf("%p\n", b)              // 0xc000076128
   fmt.Println(&a[1])                 // 0xc000076128

3. 通过make创建切片:

var a []type = make([]type, len)
a := make([]type, len)
a := make([]type, len, cap)

(1). make创建切片的内存布局:

①. 少了定义数组的过程,只不过它的底层内部创建了一个数组.
②. 两种底层都是一样在操作数组.

4. 内置函数append操作切片:

(1). 两个切片合并:
var a = []int{1, 2, 3}
var b = []int{4, 5, 6}
a = append(a, b...)
fmt.Println(a)                             // [1 2 3 4 5 6]

(2). 切片是动态的长度,如果超过固定的数组长度,会发生什么变化?
var a = [5]int{1, 2, 3, 4, 5}
b := a1[1:5]
fmt.Println(b)                                  // [2 3 4 5]
fmt.Printf("%p\t%p\n", b, &a[1])                // 0xc00006c158    0xc00006c158
fmt.Printf("len:%d\tcap:%d\n", len(b), cap(b))  // len:4   cap:4
b = append(b, 6)                                // 多次追加后,导致切片的长度大于a数组的固定长度
fmt.Printf("len:%d\tcap:%d\n", len(b), cap(b))  // len:5   cap:8
b = append(b, 7)
fmt.Println(a)                                  // [1 2 3 4 5]
fmt.Println(b)                                  // [2 3 4 5 6 7]
fmt.Printf("%p\t%p\n", b, &a[1])                // 0xc00006e0c0    0xc00006c158:. 系统底层会将数组重新拷贝一份,重新生成一个新的数组指向.. 当追加超过cap,自动会变成一倍容量:4 -> 8.

5. 切片拷贝:

s1 := []int{1, 2, 3, 4, 5}
s2 := make([]int, 1)
copy(s2, s1)
fmt.Println(s2)                  // [1],因为s2的cap是1.

s3 := []int{1, 2, 3}
s3 = append(s3, s2...)
s3 = append(s3, 4, 5, 6)

6. string原理:

string底层就是一个byte的数组,因此,也可以进行切片操作.

str := "helloworld"
a := str[0:5]
fmt.Println(a)                // hello
b := str[5:]
fmt.Println(b)                // world

(1). string的底层布局:

①. 字符串是由多个字符组成,字符串不能修改(不可变的).
   a[0] = 'a'                 // 报错
②. [ptr指针地址]  [len长度]
   ptr指针指向一个byte数组

(2). 如何改变string中的字符值?

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

str := "helloworld"
s := []byte(str)              // 定义为[]rune(str)即可解决中文乱码问题
s[0] = 'o'
str = string(s)
fmt.Pintln(str)               // oelloworld

7. 排序和查找操作:

排序操作主要在sort包中

import("sort"). sort.Ints:对整数进行排序.
   var a = [...]int{2, 5, 3, 1, 7}
   // 不能直接传a,是一个数组,值类型,就算里面排序好了,外面还是没有排序.要传一个切片.
   sort.Ints(a[:]). sort.Strings:对字符串进行排序.
   var a = [...]string{"abc", "ee", "ABC", "EFG", "vcd"}
   sort.Strings(a). sort.Float64s:对浮点数进行排序.
   var a = [...]float64{20.88, 521.10, 56.20, 63.10}
   sort.Float64(a)

(1). 用serach方法查找,必须是排好序的:

. sort.SearchInts(a []int, b int):从数组a中查找b.
   var a = [...]int{2, 5, 3, 1, 7}
   sort.Ints(a[:])
   sort.SearchInts(a, 5)       // 前提a必须有序. sort.SearchFloats(a []float64, b float64):从数组a中查找b

③. sort.SearchStrings(a []string, b string) 从数组a中查找b
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值