GO-数组和切片

一、内部实现

  1. 数组
    数组是一个长度固定的数据类型,用于存储一段具有相同类型的元素的连续块。数组存储的类型可以是内置类型,如整型或者字符串,也可以是某种结构类型。
  2. 切片
    切片是围绕动态数组的概念构建的,可以按需自动增长和缩小
    切片是一个很小的对象,对底层数组进行了抽象,并提供了相关的操作方法。切片有3个字段分别是指向底层数组的指针切片访问的元素个数(即长度)切片允许增长到的元素个数(即容量)

二、区别

2.1、声明和初始化

  1. 数组

    //声明一个包含5个元素的整型数组,并设置为零值
    var array [5]int
    //使用数组字面量声明数组
    array := [5]int{10,20,30,40,50}
    //隐式声明数组长度
    array := [...]int{10,20,30,40,50}
    //声明数组并指定特定元素
    array := [5]int{0:10,2:30}
    
    //使用make
    s2 = make([]int, 16)
    s3 = make([]int, 10, 32)
    printSlice(s2)
    printSlice(s3)
    // len=16, cap=16
    // len=10, cap=32
    
    
  2. 切片

    //使用make
    //长度和容量都是5个元素
    slice := make([]string, 5)
    //长度为3,容量为5个元素
    slice := make([]int, 3, 5)
    
    //使用字面量声明
    //长度和容量都是4个元素
    slice := []string{"red","blue","green","yellow"}
    //声明切片 并指定特定元素 长度容量都是100
    slice := []string{99:"!!"}
    

2.2、赋值

  1. 数组

    func main() {
        var array1[5]string
        array2:=[5]string{"Red","Blue","Green","Yellow","Pink"}
    
        //把array2的值复制到array1
        array1=array2
        array1[0] = "Black"
        fmt.Println(array1)
        fmt.Println(array2)
    }
    

如图数组赋值仅仅是复制数组的值

  1. 切片
func main() {
    slice := []int{1,2,3,4,5}
    slice2 := slice
    slice2[1] = 100
    fmt.Println(slice)
    fmt.Println(slice2)
}

切片赋值,仅仅是复制切片的指针、长度和容量

2.3、遍历

  1. 数组的遍历
func arrRange() {
    arr1 := [...]int{2, 4, 6, 8, 10}
    //传统方法
    for i := 0; i < len(arr1); i++ {
        fmt.Println(arr1[i])
    }
	//range方法
    for _, value := range arr1 {
        fmt.Println(value)
    }

2.4、值传递 && 引用传递

2.4.1、数组变量

1. 值传递

GO中数组就是一个变量 --> 不同大小就是不同类型

func printArray(arr [5]int) {
    arr[0] = 100
    for _, v := range arr {
        println(v)
    }
}

func main() {
    arr1 := [5]int{1, 2, 3, 4, 5}
    arr2 := [3]int{1, 2, 3}
    //传递成功
    printArray(arr1)
    //失败
    printArray(arr2)
}

错误:

cannot use arr2 (type [3]int) as type [5]int in argument to printArray
  • 第一个成功

  • 第二个不成功,类型不匹配

    1. 数组值修改 – 引用传递
func printArray2(arr *[5]int) {
    arr[0] = 100
    for _, v := range arr {
        println(v)
    }
}

func main() {
    arr1 := [5]int{1, 2, 3, 4, 5}
    printArray(arr1)
    printArray2(&arr1)
    fmt.Println(arr1)
}

2.4.2、切片

Slice 本身没有数据,只是对底层 array 的一个 view,其截取大小只是修改了切片中的ptr和len但是cap为从当前ptr算起到,原切片长度 ^4ae9ee

  • slice 可以向后扩展,不可以向前扩展

  • s[i]不可以超越len(s),向后扩展不可以超越cap(s)
    如图:
    ^a7c516

    1. 指针引用传递
      切片截取:
func main() {
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    fmt.Println("arr[2:6] = ", arr[2:6])
    fmt.Println("arr[2:6] = ", arr[:6])
    fmt.Println("arr[2:6] = ", arr[2:])
    fmt.Println("arr[2:6] = ", arr[:])
}

输出:

arr[2:6] =  [2 3 4 5]
arr[2:6] =  [0 1 2 3 4 5]
arr[2:6] =  [2 3 4 5 6 7]
arr[2:6] =  [0 1 2 3 4 5 6 7]

切片数据修改:

func updateSlice(s []int) {
    s[0] = 100
}

func main() {
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    s1 := arr[2:]
    s2 := arr[:]
    fmt.Println(s2) // [0 1 2 3 4 5 6 7]
    fmt.Println("After updateSlice")
    updateSlice(s1)
    fmt.Println(s1) // [100 3 4 5 6 7]
    fmt.Println(arr) // [0 1 100 3 4 5 6 7]
}

越界问题:

  1. 例一:✅
arr = [...]int{0,1,2,3,4,5,6,7}
s1 = arr[2:6]
s2 = s1[3:6]
fmt.Println("s1 = ",s1)
fmt.Println("s2 = ",s2)

结果:

s1 =  [2 3 4 5]
s2 =  [5 6 7]
  1. 例2:❌
fmt.Println(s1[4])

结果:

panic: runtime error: index out of range

原因:[[#^4ae9ee]]

2.5、扩容

2.5.1、切片扩容 Append

arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:6]
s2 := s1[3:5]
s3 := append(s2, 10)
s4 := append(s3, 11)
s5 := append(s4, 12)
fmt.Println(s1, s2, s3, s4, s5)

// [2 3 4 5] [5 6] [5 6 10] [5 6 10 11] [5 6 10 11 12]

capacity满了才扩容,每次扩容两倍,所以和java一样,数组最好知道容量,上来就建好。

2.5.1、数组扩容

只能复制

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会拯救世界的SuperMan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值