go语言基础之数组和切片

go语言基础之数组
Array
数组是同一种数据类型的集合,Go语言中,数组从声明时就确定,使用时可以修改数组成员,数组的大小不可以变化。
数组是值类型,,将数组赋值给另一个变量,就相当于复制了一份,就变成了两个数组,两个数组之间的操作不冲突
注意:数组支持==和!=操作,因为数组是值类型

package main

import "fmt"
func main() {
    
    
    //数组
    //存放元素的容器
    //必须指定数组存放的类型和容量
    //数组的长度是数组类型的一部分
    var ar [3]int
    fmt.Printf("%T", ar)
    //数组的初始化
    //如果我们不初始化数组,那么数组里的元素默认都是二进制的零值(bool:false  int和flaot:0  string:"")
    //初始化方式1
    ar = [3]int{
    
    1, 2, 3}
    fmt.Printf("%v\n", ar)
    //初始化方式2
    //根据初始值自动推断数组的长度
    arr := [...]int{
    
    1, 2, 3, 4, 5, 6}
    fmt.Printf("%v\n", arr)
    //初始化方式3
    //根据索引初始化
    array := [3]int{
    
    1: 1, 2: 1}
    fmt.Printf("%v\n", array)
    //遍历数组
    for i := 0; i < len(arr); i++ {
    
    
        fmt.Println(arr[i])
    }
    for i, v := range arr {
    
    
        fmt.Printf("%d--%d\n", i, v)
    }
    //多维数组
    var ar1 [3][2]int
    ar1 = [3][2]int{
    
    
        [2]int{
    
    1, 2},
        [2]int{
    
    3, 4},
        [2]int{
    
    5, 6},
    }
    fmt.Println(ar1)
    //遍历多维数组
    for _, v := range ar1 {
    
    
        for _, v1 := range v {
    
    
            fmt.Println(v1)
        }
    }

切片(slice)
切片是一个拥有相同数据类型元素的,可变长度的序列,他是基于数组类型做的一个封装,它非常灵活,支持自动扩容,切片是一个引用类型,他的内容结构包含地址,长度和容量,切片用于快速操作一块数据集合。

package main

import "fmt"
func main() {
    
    
    //切片的定义
    var slice []int
    //切片的初始化
    slice = []int{
    
    1, 2, 3, 4, 5, 6, 7}
    fmt.Println(slice)
    //数组的长度和数组的容量
    fmt.Println(len(slice))
    fmt.Println(cap(slice))
    //数组的切片,得到一个切片类型
    array := [...]int{
    
    1, 2, 3, 4, 5, 6, 7, 8, 9}
    arrsl := array[0:4] //数组的切片
    //切片的容量是指底,切片的第一个元素,到底层数组的最后一个元素
    //比如,切片是[3:],那么切片的容量就是len(array)-3
    fmt.Printf("%T--%v--%d\n", arrsl, arrsl, cap(arrsl))
    //切片是引用类型,他都指向了底层的一个数组,数组发生改动,那么切片也发生改动
    array[1] = 200
    fmt.Println(arrsl)
}

使用make()函数构造切片。

package main

import "fmt"
func main() {
    
     
    //使用make()函数构造一个切片,参数1切片的类型,参数2切片的长度,参数3切片容量
    me := make([]int, 5, 10)
    fmt.Printf("%T--%d--%d", me, len(me), cap(me))
}

切片的本质
切片就是一个框,框住了一块连续的内存,这块内存只能存储想同类型的值
切片不能直接比较
切片之间是不能比较的,我们不能使用==操作符来判断两个切片的元素是否相同,切片的唯一合法比较适合nil进行比较,一个nil值得切片是没有底层数组的,一个nil值得切片的长度和容量都是0,但是我们不能说一个长度和容量都是0的切片是nil,所以判断切片是否为空,用len(s) == 0判断,不应该用s == nil判断。

package main

import "fmt"
func main() {
    
    
    me := make([]int, 0)
    fmt.Printf("%T--%d--%d", me, len(me), cap(me))
}
切片的赋值与遍历
package main

import "fmt"
func main() {
    
    
    me := make([]int, 0)
    fmt.Printf("%T--%d--%d\n", me, len(me), cap(me))
    //切片的赋值
    s1 := []int{
    
    1, 2, 3}
    s2 := s1
    s2[1] = 1000
    fmt.Printf("%v--%v\n", s1, s2)
    fmt.Println("---------")
    //切片的遍历
    for i := 0; i < len(s1); i++ {
    
    
        fmt.Println(s1[i])
    }
    fmt.Println("----------")
    for i, v := range s1 {
    
    
        fmt.Printf("%d--%d\n", i, v)
    }
}

使用append函数为切片追加元素
Go语言的内建函数可以为append,可以动态添加元素,每个切片都会指向一个底层数组,这个数组能容纳一定数量的元素,当底层数组不能容纳新增的元素时,切片就会按照一定的扩容策略进行自动扩容,此时该切片指向的底层数组就会更换,扩容操作发生在append调用时。
append的扩容策略。
首先判断,如果新增的容量,大于旧的容量的2倍,最终容量就是新申请的容量。
否组判断,如果旧的切片的容量小于1024,那么新容量就是旧容量的2倍
否则判断,如果旧的切片的容量大于1042,那么新的容量就是旧的容量加上旧的容量的1/4
如果计算容量溢出,那么新的容量,就是新申请的容量
注意:元素类型不同的切片,扩容策略也是不同的

package main

import "fmt"
func main() {
    
    
    s1 := []string{
    
    "北京", "上海", "广州"}
    //切片不可以使用索引的方式添加数据,会报(索引越界错误)
    // s1[3] = "深圳"
    //在切片中追加数据
    //方式1,append的第一个参数是被添加的目标切片,第二个参数是添加的值
    s1 = append(s1, "深圳")
    fmt.Println("方式1")
    fmt.Println(s1)
    fmt.Printf("%d--%d\n", len(s1), cap(s1))
    //方式2,添加多个值
    s1 = append(s1, "围场", "承德")
    fmt.Println("方式2")
    fmt.Println(s1)
    fmt.Printf("%d--%d\n", len(s1), cap(s1))
    //方式3,在切片中,追加一个切片
    var slice1 = []string{
    
    "廊坊", "天津"}
    s1 = append(s1, slice1...)
    fmt.Println("方式2")
    fmt.Println(s1)
    fmt.Printf("%d--%d\n", len(s1), cap(s1))
    // 切片的拷贝 copy函数
    // copy函数,拷贝的切片会重新生成一个底层数组,和旧的底层数组不冲突
    // 重新定义一个切片,类型,长度都要和以前切片一致
    var ss1 = make([]string, len(s1), cap(s1))
    ss2 := s1
    copy(ss1, s1)
    fmt.Printf("%v--%d--%d\n", ss1, len(ss1), cap(ss1))
    ss2[0] = "成都"
    fmt.Printf("%v--%v--%v\n", ss1, ss2, s1)
    //在切片中,没有内置的删除函数,所以自己实现一段,实现删除功能的代码
    a1 := [...]int{
    
    1, 2, 3, 4, 5, 6, 7, 8, 9}
    slice := a1[:]
    //删除索引为2的数据
    slice = append(slice[:2], slice[3:]...)
    //因为在append函数中我们操作的是指向同一个数组的切片,所以我们就相当于在操作数组
    //我们的目标切片是数组的1,2,我们后面追加的数据,就相当于是,依次修改了,底层数组中的代码
    fmt.Printf("%v\n%v", slice, a1)
}

猜你喜欢

转载自blog.csdn.net/weixin_44865158/article/details/114527945