Go基础之数组与切片

一.数组

  • 数组的声明

方式一 var 声明

var arr1 [5]int      //规定大小,不需赋初值 

方式二 := 声明  需要赋初值

arr2 := [3]int {0,0,0}       //采用快速赋值符时,规定数组大小,且需要给数组赋初值

arr3 := [...]int{1,2,3,4,5,6}   //通过三个点,让编译器自动计算数组的大小

  • 数组的遍历

使用"range"关键字,可以同时获得数组元素的下标和值

for i := 0; i<len(arr3); i++ {        //方式1

    fmt.Println(arr3[i])

}

for i := range arr3 {        //方式2 只获得下标

    fmt.Println(arr3[i])

}

for _, v := range arr3 {      //方式3 只获得值

    fmt,Println(v)

for i, v := range arr3 {       //方式4 同时获得下标和值

    fmt,Println(i, v)

go语言中的"range"

  • 意义明确,美观
  • C++中没有类似操作
  • Java/Python 只能for each 元素的值,不能同时获得下标和值
  • 注意,go语言中的数组是值类型
  • 数组必须规定其大小,[10]int 和[20]int 是不同的数据类型
  • func f(arr [10]int) 会拷贝数组,这一点与其他大多语言都不同,其他语言的数组一般多为引用传递
  • go语言中一般不直接使用数组,而是使用切片

二.切片(slice)

  • 初识切片

arr := [...]int{0,1,2,3,4,5,6,7}

s := arr[2:6]     //这里的s 就是一个切片,其值为[2,3,4,5],切片内的范围是左闭右开的

s1 := arr[:6]

s2 := arr[2:]

s3 := arr[:]        //s1,s2,s3 均是切片

 

另外,不加长度的数组就是一个slice

func f(s [ ]int)      //这里的s是一个slice

  • slice本身是没有数据的,slice是对底层数组的一个view,slice是按引用传递的 
  • 对slice操作实际上就是对slice对应的底层数组的操作

package main

import (
    "fmt"
)
func updateArr(s []int){
    s[0] = 100
    fmt.Println(s) 
}
func main(){
    arr := [8]int{0,1,2,3,4,5,6,7}
    s1 := arr[2:6]
    s2 := arr[:]
    
    fmt.Println("Arr:",arr)
    fmt.Println("s1:",s1)
    fmt.Println("s2:",s2)
    
    fmt.Println("After update s1:")
    fmt.Print("s1:")
    updateArr(s1)
    fmt.Println("Arr:",arr)
    
    fmt.Println("After update s2:")
    fmt.Print("s2:")
    updateArr(s2)
    fmt.Println("Arr:",arr)
}
输出结果:

Arr: [0 1 2 3 4 5 6 7]
s1: [2 3 4 5]
s2: [0 1 2 3 4 5 6 7]
After update s1:
s1:[100 3 4 5]
Arr: [0 1 100 3 4 5 6 7]
After update s2:
s2:[100 1 100 3 4 5 6 7]
Arr: [100 1 100 3 4 5 6 7]

  • slice的"reslice"操作

package main

import (
    "fmt"
)
func main(){
    arr := [8]int{0,1,2,3,4,5,6,7}
 
    //reslice
    s := arr[:]
    fmt.Println(s)
    s = s[2:6]    //注意 这里是"="而不是":="
    fmt.Println(s)
    s = s[1:3]
    fmt.Println(s) 
}
输出结果:

[0 1 2 3 4 5 6 7]
[2 3 4 5]
[3 4]

  • slice是可以扩展的 ,扩展只能向后扩展,而不能向前扩展
  • 每个slice都是对其所对应的数组的一个view

package main

import (
    "fmt"
)

func main(){
    arr := [8]int{0,1,2,3,4,5,6,7}


    //extend
    s1 := arr[2:6]
    s2 := s1[3:5]     //s2即s1[3],s1[4], 但这里s1中只有4个元素,不存在s1[4], 若单独  fmt.Println(s1[4])  会报错 
    fmt.Println(s1)
    fmt.Println(s2)
}
但是,输出结果:

[2 3 4 5]
[5 6]

  • slice的实现,对slice的len和cap的理解 
  • slice中,s[i] 不可超越其len
  • slice的扩展范围不能超过其cap  即s[i:cap]
  • 可以通过len(s), cap(s)来查看slice的len和cap值

Go基础之数组与切片

 

  • 用append()向slice添加元素,  s = append(s,val)
  • 向slice添加元素时,如果超过其cap,系统会重新分配一个更大的底层数组,原来的底层数组如果没有再被使用就会被回收掉,新的cap为原来cap的两倍
  • 由于是值传递,所以必须接受append()的返回值 
  • 添加元素时slice的cap有可能改变,cap改变则意味则新的底层数组的出现
  • slice始终操作的都是底层数组中的数据,slice本身没有数据,故append改变的也是底层数组,如果append没有超出其cap,则是底层数组中元素的替换

package main

import (
    "fmt"
)

func main(){
    arr := [...]int{0,1,2,3,4,5,6,7}

    //append
    s1 := arr[2:6]
    fmt.Println("Arr:",arr)
    fmt.Println("s1:",s1)
    
    s1 = append(s1,10)
    fmt.Println("After first append:")
    fmt.Println("s1:",s1)
    fmt.Println("arr:",arr)
    
    s1 = append(s1,11)
    fmt.Println("After second append:")
    fmt.Println("s1:",s1)
    fmt.Println(cap(s1))
    fmt.Println("arr:",arr)
    
    s1 = append(s1,12)
    fmt.Println("After third append:")
    fmt.Println("s1:",s1)
    fmt.Println(cap(s1))
    fmt.Println("arr:",arr)    
}
 

输出结果:

Arr: [0 1 2 3 4 5 6 7]
s1: [2 3 4 5]
After first append:
s1: [2 3 4 5 10]
arr: [0 1 2 3 4 5 10 7]
After second append:
s1: [2 3 4 5 10 11]
6
arr: [0 1 2 3 4 5 10 11]
After third append:
s1: [2 3 4 5 10 11 12]
12
arr: [0 1 2 3 4 5 10 11]

  •  go语言中,每声明一个变量,系统都会给它创建一个"Zero value"
  • Zero value of slice is "nil"
  • 实际操作中,slice的几种创建方式:
  • 方式一

       var s1 [ ]int   

 

  • 方式二  

       s2 := [ ]int {1,2,3,4}   

            这行代码实行了两步操作:

           1> 创建了一个底层数组 [...]int{1,2,3,4}

            2> 将底层数组的view赋值给切片s2

 

  • 方式三

        s3 := make([ ]int, len)

 

  • 方式四

        s4 := make([ ]int, len, cap)

 

  • slice的copy操作

copy(s1, s2)     //将s2中的元素copy到s1中 

  • slice 的delete操作

1> 删除中间某个元素

      s = append(s[:5], s[6:]...)       //删除了s中的s[5]

2> 删除头或尾

  s 的头:s[0]

       s 的尾:s[len(s)-1]

       删除头操作: s = s[1:]

       删除尾操作:s = s[:len(s)-1]