go基础笔记-切片


切片的基本介绍
(1)切片的英文是 slice
(2)切片是数组的一个引用,因此切片是引用类型,在进行传递时,遵守引用传递的机制。
(3)切片的使用和数组类似,遍历切片、访问切片的元素和求切片长度 len(slice)都一样。
(4)切片的长度是可以变化的,因此切片是一个可以动态变化数组。
(5)切片定义的基本语法:
var 切片名 []类型
比如:var a [] int

 

切片的使用
第一种方式:
定义一个切片,然后让切片去引用一个已经创建好的数组。

案例:
func main() {
    // 切片入门案例:
    var intArr [5]int = [...]int{1, 22, 33, 66, 99}
    //声明/定义一个切片
    slice := intArr[1:3]
   
    fmt.Println("intArr=", intArr)
    fmt.Println("slice 的元素是 =", slice) //  22, 33
    fmt.Println("slice 的元素个数 =", len(slice)) // 2
    fmt.Println("slice 的容量 =", cap(slice)) // 切片的容量是可以动态变化 
    // 上述代码说明:
    // slice 就是切片名
    // intArr[1:3] 表示 slice 引用到intArr这个数组 
    // 引用intArr数组的起始下标为 1 , 最后的下标为3(但是不包含3) 
}    


第二种方式:
通过 make 来创建切片.
基本语法:
var 切片名 []type = make([]type, len, [cap])

参数说明: type: 就是数据类型 len : 大小 cap :指定切片容量,可选, 如果你分配了 cap,则要求 cap>=len.
通过 make 方式创建切片可以指定切片的大小和容量
如果没有给切片的各个元素赋值,那么就会使用默认值    [ int , float=> 0 string =>”” bool =>false]

案例:
func main() {
    //演示切片的使用 make
    var slice []float64 = make([]float64, 5, 10)
    slice[1] = 10
    slice[3] = 20
    //对于切片,必须make使用.
    fmt.Println(slice)
    fmt.Println("slice的size=", len(slice))
    fmt.Println("slice的cap=", cap(slice))
}    


第 3 种方式:
定义一个切片,直接就指定具体数组,使用原理类似 make 的方式



切片的遍历
切片的遍历和数组一样,也有两种方式
方式一:for 循环常规方式遍历
//使用常规的for循环遍历切片
var arr [5]int = [...]int{10, 20, 30, 40, 50}
slice := arr[1:4]
for i := 0; i < len(slice); i++ {
    fmt.Printf("slice[%v]=%v ", i, slice[i])
}


方式二:for-range 结构遍历切片
var arr [5]int = [...]int{10, 20, 30, 40, 50}
slice := arr[1:4]
//使用for--range 方式遍历切片
for i, v := range slice {
    fmt.Printf("i=%v v=%v \n", i, v)
}



切片也可以简写:
var slice = arr[0:end]              可以简写 var slice = arr[:end]
var slice = arr[start:len(arr)]     可以简写: var slice = arr[start:]
var slice = arr[0:len(arr)]         可以简写: var slice = arr[:]



切片可以继续切片
func main() {
    // 切片可以继续切片案例演示
    var arr [5]int = [...]int{10,20,30,40,50}
    slice := arr[1:4]
    for i:=0;i < len(slice);i++ {
        fmt.Printf("slice[%v]=%v\n",i,slice[i])
    }
    fmt.Println()
    for i,v := range slice{
        fmt.Printf("i=%v v=%v \n",i,v)
    }
    slice2 := slice[1:2]
    slice2[0] = 1000
    fmt.Println("slice2=",slice2)
    fmt.Println("slice=",slice)
    fmt.Println("arr=",arr)
}    



用 append 内置函数,可以对切片进行动态追加

func main() {
    // 用 append 内置函数,可以对切片进行动态追加
    var slice3 []int = []int{10,20,30,40,50}
    fmt.Println("slice3",slice3)
    slice3 = append(slice3,60,70)
    fmt.Println("slice3",slice3)
    slice3 = append(slice3,slice3...)
    fmt.Println("slice3",slice3)   
} 

切片 append 操作的底层原理分析:
切片 append 操作的本质就是对数组扩容
go 底层会创建一下新的数组 newArr(安装扩容后大小)
将 slice 原来包含的元素拷贝到新的数组 newArr
slice 重新引用到 newArr
注意 newArr 是在底层来维护的,程序员不可见.



切片的拷贝操作
切片使用 copy 内置函数完成拷贝
语法: func copy(dst,src []type) int
案例演示:
func main() {
    // 切片的拷贝操作
    var slice4 []int = []int{1, 2, 3, 4, 5}
    var slice5 = make([]int, 10)
    copy(slice5, slice4)
    fmt.Println("slice4=", slice4)  // 1 2 3 4 5 
    fmt.Println("slice5=", slice5)  // 1 2 3 4 5 0 0 0 0 0 
    slice4[1] = 100                    
    fmt.Println("slice4=", slice4)  // 1 2 3 4 5 
    fmt.Println("slice5=", slice5)  // 1 100 3 4 5 0 0 0 0 0  
} 

对上面代码的说明:
copy(para1, para2) 参数的数据类型是切片
按照上面的代码来看, slice4 和 slice5 的数据空间是独立,相互不影响,也就是说 slice4[0]= 999, slice5[0] 仍然是 1



string和slice
string 底层是一个 byte 数组,因此 string 也可以进行切片处理

案例演示:
//string底层是一个byte数组,因此string也可以进行切片处理
str := "hello@xxl"
//使用切片获取到 xxl
slice := str[6:] 
fmt.Println("slice=", slice)


string 是不可变的,也就说不能通过 str[0] = 'z' 方式来修改字符串

如果需要修改字符串,可以先将 string -> []byte / 或者 []rune -> 修改 -> 重写转成 string

//"hello@xxl" =>改成 "zello@xxl"
str := "hello@xxl"
arr1 := []byte(str) 
arr1[0] = 'z'
str = string(arr1)
fmt.Println("str=", str)


细节,我们转成[]byte后,可以处理英文和数字,但是不能处理中文
原因是 []byte 字节来处理 ,而一个汉字,是3个字节,因此就会出现乱码
解决方法是 将  string 转成 []rune 即可, 因为 []rune是按字符处理,兼容汉字

arr1 := []rune(str) 
arr1[0] = ''
str = string(arr1)
fmt.Println("str=", str)

猜你喜欢

转载自www.cnblogs.com/liang545621/p/13402672.html