1. 切片的英文是slice
2. 切片是数组的一个引用,因此切片是引用数据类型,在进行传递时,遵守引用传递的机制
3. 切片的使用和数组相似,遍历切片、访问切片的元素和求切片长度len(slice)都一样
4. 切片的长度是可以变化的,因此切片是一个可以动态变化数组
var 变量名 []类型
//和数组类似,不过不需要定义长度
package main
import (
"fmt"
)
func main() {
var intArr [5]int = [...]int{1,2,3,4,5} //这里定义一个数组
slice := intArr[1:3] //基于这个数组,我们生成一个切片 其中[1:3]表示数组中1、2索引位的数据,不包括3索引
fmt.Println("intArr=",intArr)
fmt.Println("slice 的元素是=",slice) //切片的值
fmt.Println("slice 的元素个数",len(slice)) //切片的长度
fmt.Println("slice 的容量 =",cap(intArr)) //切片的容量
//切片的容量一般是已经存放元素大小的一倍以上
}
返回
intArr= [1 2 3 4 5]
slice 的元素是= [2 3]
slice 的元素个数 2
slice 的容量 = 5 //切片的容量一半是已经存放元素的一倍以上
var intArr [5]int = [...]int{1,2,3,4,5}
定义了一个intArr的数组变量,会在内存空间划分一块区域
在这块区域中划分5块空间单独存储5个值
在定义切片时,他会指定数组的值的内存空间 slice := intArr[1:3]
package main
import (
"fmt"
)
func main() {
var intArr [5]int = [...]int{1,2,3,4,5}
slice := intArr[1:3]
//下面的代码可以看到,intArr数组的索引位1和切片的索引位0是相同的
//也证明了上面是正确的
fmt.Println(&intArr[1])
fmt.Println(&slice[0])
}
返回
0xc00000e458
0xc00000e458
1、slice 里面存放着3种东西
//原数组中索引位的的内存地址
// len = 2 存放切片的长度
// cap=4 存放切片的总容量 一般为长度的一倍以上
2. slice 切片是一个引用类型的,和之前的值数据类型不同的是.值类型是把他当一个值作为存放的
而切片相当于是一个软连接的存在,如果修改了slice的值,那么数组的值也会被修改
package main
import (
"fmt"
)
func main() {
var intArr [5]int = [...]int{1,2,3,4,5}
slice := intArr[1:3]
//修改数据
slice[0] = 100
fmt.Println(intArr)
}
//[1 100 3 4 5]
var 切片名 []type = make([],len,[cap])
#参数说明
type //数据类型
len //切片元素数量
cap //指定切片容量 #可选,如果要分配了cap,则要求cap至少大于等于len
package main
import (
"fmt"
)
func main(){
var slice []int = make([]int,4,10) //设置切片类型为int,元素数量为4,空间大小为10,
fmt.Println(slice) //默认值为0 0 0 0 因为元素数量为4
fmt.Println("sclice len=",len(slice),"slice cap",cap(slice))
slice[0] = 100
slice[2] = 200
fmt.Println(slice)
}
返回
[0 0 0 0]
sclice len= 4 slice cap 10
[100 0 200 0]
1. 通过make方式创建切片可以指定切片的大小和容量
2. 如果没有给切片的各个元素赋值,那么就会使用基本数据类型的默认值
3. 通过make方式创建的切片对应的数组是由make底层维护,对外不可见,只能通过slice去访问各个元素
package main
import (
"fmt"
)
func main(){
var slice []string = []string{"tom","jack","mary"}
fmt.Println(slice)
fmt.Println(len(slice))
fmt.Println(cap(slice))
}
返回
[tom jack mary]
3
3 //这样定义,cap默认和元素数量一致
和数组类型,使用for循环 或者 for-range
package main
import (
"fmt"
)
func main(){
var arr [5]int = [...]int{10,20,30,40,50}
slice := arr[1:4] //20,30,40
for i := 0; i < len(slice); i++{
fmt.Printf("slice[%v]=%v\n",i,slice[i])
}
}
package main
import (
"fmt"
)
func main(){
var arr [5]int = [...]int{10,20,30,40,50}
slice := arr[1:4] //20,30,40
//for-range (这里i可以不要)
for i, v := range slice {
fmt.Printf("i=%v v=%v\n",i,v)
}
}
var slice = arr[startindex:endlindex]
//切片初始化时,从arr数组下标为startindex,取值到下标为endindex的元素,不包含arr[endlindex]
1. var slice = arr[0:end]
//可以简写成 var slice =arr[:end]
2. var slice = arr[start:len(arr)]
//可以简写成 var slice =arr[start:]
3. var slice = arr[0:len(arr)]
//可以简写: var slice=arr[:]
cap是一个内置函数,用于统计切片的容量,即最大可以存放多少个元素
//使用方法
// cap(切片)
切片定义完成后,还不能使用,因为本身是一个空的,需要让其引用到一个数组,
或者说 make一个空间供切片来使用
package main
import "fmt"
func main(){
var slice3 []int = []int{100,200,300}
fmt.Println("slice3",slice3)
slice3 = append(slice3, slice3...) //给slice这个切片追加自身的切片
//... 是固定格式
//后面的必须是切片或者具体的值,不能是数组
fmt.Println(slice3)
}
返回
slice3 [100 200 300]
[100 200 300 100 200 300]
package main
import "fmt"
func main(){
//定义数组,定义切片取值
var shuzu [5]int = [5]int{1,2,3,4,5}
var slice = shuzu[1:4]
fmt.Println(slice)
//追加
slice = append(slice, 10,20,30,40)
fmt.Println(slice)
}
返回
[2 3 4]
[2 3 4 10 20 30 40]
1. 切片append操作的本质就是对数组进行扩容
2. go底层会创建一下新的数组,newArr(安装扩容后大小)
3. 将slice原来包含的元素拷贝到新的数组newArr
4. slice重新引用到newArr
5. 注意newArr是在底层维护的,不可见
package main
import "fmt"
func main(){
//定义一个切片
var slice3 []int = []int{100,200,300}
fmt.Println("slice3",slice3)
//append给切片追加元素
//这里append相当于是新创建了一个数组,然后将这个数组赋值给slice4
slice4 := append(slice3,400)
fmt.Println(slice4)
}
返回
slice3 [100 200 300]
[100 200 300 400]
var intArr [3]int = [...]int{100,200,300} //定义一个数组
slice := intArr[1:3] //基于数组创建一个切片
#通过append添加值
slice3 = append(slice3, 400,500,600)
append会根据原先切片的元素和要新增的元素,来判断新增数组的空间大小(cap=6),因为是int类型默认值都为0
他会先读取原先切片指定的数组的值复制到临时数组中
然后将append后面要添加的值再追加到该数组中
最后将切片指向这个新的数组
而重新指定指针后,原先的数组就变成垃圾了,就会被回收
package main
import "fmt"
func main(){
var a []int = []int{1,2,3,4,5} //定义一个切片 [1 2 3 4 5]
var slice = make([]int,10) //定义一个切片空间为10 [0 0 0 0 0 0 0 0 0 0]
fmt.Println(slice)
copy(slice,a) //将a切片的的值拷贝给slice切片 [1 2 3 4 5 0 0 0 0 0]
fmt.Println(slice,a)
}
当slice切片的空间大小不足以包含a切片的所有值的适合,会损失超出的值
package main
import "fmt"
func main(){
var a []int = []int {1,2,3,4,5}
var slice =make([]int,1)
fmt.Println(slice)
copy(slice,a)
fmt.Println(slice)
}
返回
[0]
[1]
分析两段代码
package main
import "fmt"
func main(){
var slice []int //定义一个切片 目前为空
var arr [5]int = [...]int {1,2,3,4,5} //定义一个数组
slice =arr[:] //将数组的值全交给切片
var slice2 = slice //声明slice2 然后将切片的值交给slice2切片
slice2[0] = 10
fmt.Println(slice2) //输出数组、slice、slice2切片
fmt.Println(slice)
fmt.Println(arr)
}
[10 2 3 4 5]
[10 2 3 4 5]
[10 2 3 4 5]
//数组被切片拿到后,实际上 切片的值是指定的数组的内存地址
//再将切片交给其他切片后,实际上他里面的值不变还是指向数组的内存地址
//在上面我们slice2[0] = 10 给切片的值做修改的时候,实际上是修改了arr数组的值
//然而slice和slice2都是指向arr数组来提供数据的,所以3个值相同
//这就是引用数据类型的特点,值不是我自己的
package main
import "fmt"
func test(slice []int){
slice[0] = 100 //切片是引用数据类型,可以在不同的函数中直接修改值
}
func main(){
var slice = []int{1,2,3,4}
fmt.Println("slice=",slice)
test(slice)
fmt.Println("slice=",slice)
}
返回
slice= [1 2 3 4]
slice= [100 2 3 4]
//事实证明,如果我们将切片传入到其他函数中后,那么相当于是一个全局的变量,在任何地方都可以修改
//slice是一个切片,切片是引用类型的值,那么他func test(slice []int) 传递的并不是切片的值,而是切片指定数组的内存地址
//test 函数中的slice 实际上是指定到了main中的slice,因此可以直接被修改
package main
import "fmt"
func main(){
str := "hello@atguigu" //string底层是一个byte数组,一昵称string也可以进行切片处理
slice := str[6:] //使用切片获取到atguigu
fmt.Println(slice)
}
返回
atguigu
//a b c d 字符串的底层是一个byte的数组
//str这个切片指向了byte数组的首地址
//因为他是一个切片,所以他可以使用切片的方法和函数
str[0] = 'z' #这样是不可用的
#报错的原因
string是不可变的
package main
import "fmt"
//如果需要修改字符串,可以先将string 转换为byte 或者rune,修改,重新转成字符串
func main(){
str := "hello@atguigu"
slice := str[6:]
fmt.Println(slice)
//如果非要修改字符串,如下
arr1 := []byte(str) //先转成byte数组
arr1[0] = 'z' //修改
str = string(arr1) //转回字符串
fmt.Println(str)
}
返回
atguigu
zello@atguigu
我们转换成[]byte 后可以处理英文和数字,但是不能处理中文
原因是[]byte字节来处理,而一个汉字,是3个字节,因此就会出现乱码
#解决方法
将string转换为[]rune即可, 因为runc是兼容中文的,他是按照字符进行处理的,
package main
import "fmt"
func main(){
str := "hello@atguigu"
slice := str[6:]
fmt.Println(slice)
//修改为rune,添加的字符为的
arr1 := []rune(str)
arr1[0] = '的'
str = string(arr1)
fmt.Println(str)
}
//atguigu
//的ello@atguigu
编写一个函数 fbn(n int) 要求完成下面的功能
1, 可以接收一个n int
2. 能够将斐波那契的数列放到切片重
3. 提示 斐波那契的数列形式
arr[0] = 1;
arr[1] = 1
arr[2] = 2
arr[3] = 3
arr[4] = 5
arr[5] = 8
package main
import (
"fmt"
)
func fbn(n int) []uint{
fbnSlice := make([]uint,n) //初始化切片 设置空间大小为n 10
fbnSlice[0] = 1 //因为0和1的索引位的值,斐波那契都为1,那么可以写死
fbnSlice[1] = 1
for i := 2; i < n; i++ { //通过循环来存放斐波那契的数列,索引位值从2开始
fbnSlice[i] = fbnSlice[i-1] + fbnSlice[i-2] //斐波那契的值都是前两位相加的值
//-1 前一位
//-2 前前一位
//然后将这两位值相加后赋值
//下波循环再拿最新的值
}
return fbnSlice
}
func main(){
fbnSlice := fbn(10) //定义要获取的元素的个数
fmt.Println(fbnSlice)
}
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- oldu.cn 版权所有 浙ICP备2024123271号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务