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

1. slice:

go 复制代码
①. 基础:
   a. 切片是指向数组的一个引用,因此切片是引用类型.
   b. 切片的长度可以改变.因此,切片是一个可变的数组.
   c. 切片遍历方式和数组一样,可以用len()求长度.

②. 定义:
   var 变量名 []类型         // 与数组的区别是没有写长度
   a. var arr []string

③. len是长度、cap是容量:
   a. cap表示slice最大的容量.
   b. 大小关系:
      0 <= len(slice) <= (array:slice引用的数组).

2. 通过数组创建切片:

go 复制代码
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). 数组创建切片的内存布局:

go 复制代码
①. 如上图数据结构:
   [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创建切片:

go 复制代码
var a []type = make([]type, len)
a := make([]type, len)
a := make([]type, len, cap)

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

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

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

go 复制代码
(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. 切片拷贝:

go 复制代码
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的数组,因此,也可以进行切片操作.

go 复制代码
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中字符,需要如下操作:

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

7. 排序和查找操作:

排序操作主要在sort包中

go 复制代码
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方法查找,必须是排好序的:

go 复制代码
①. 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
相关推荐
古法老登瞎折腾21 小时前
大数据智能运维实战(十一):运维 MCP 的工程化——权限、限流、审计与错误处理
java·大数据·运维·spring ai·mcp
康小汪21 小时前
AI 写 Vue 总写成同一个味道:给它装 Skills,装的不是知识是边界
前端·vue.js·人工智能·ai编程·最佳实践
智能运维指南1 天前
研制过程“两张皮“怎么破:研制一体化支撑平台的定位、能力边界与落地前提
java·前端·人工智能·嘉为蓝鲸
yz_aiks1 天前
Spring AI 2.1 ChatMemory 已过时用什么替代:迁移到 Session Memory 实战(JDBC 存储与会话压缩)
java·spring boot·大模型·ai agent·spring ai
金銀銅鐵1 天前
[Java] 用 GUI 展示 EnumMap 增删键值对时的内部变化
java·后端·ai编程
学长毕设1 天前
基于SpringBoot的上门洗车服务系统设计与实现
java·spring boot·后端
jason成都1 天前
RTKLIB-Java 多基线联合RTK:FIX率从0%到91.5%的三层根因修复
java·gnss·rtklib·rtklib_java
鱼宵1 天前
Stream 终端操作一次讲透:collect、count、reduce 怎么选
java·stream·终端操作
白山编程大哥1 天前
Java 后端如何优雅地把 List 集合返回给前端
java·前端·list
Linux运维技术栈1 天前
CVE-2026-91403 高危漏洞修复:Rocky Linux 9 多版本 JDK 环境清理实操
java·linux·运维