go 中的slice与数组

数组

go中的数组与C语言中的数组类似,但是不同的是C中的数组名其实还是指针,在作为参数传递的过程中会退化为指针,而go语言则是在编译期间就确定其大小,然后始终是作为值传递的。

初始化

  • [5] int {1,2,3,4,5}

    长度为5的数组,其元素值依次为:1,2,3,4,5

  • [5] int {1,2}

    长度为5的数组,其元素值依次为:1,2,0,0,0 。在初始化时没有指定初值的元素将会赋值为其元素类型int的默认值0,string的默认值是""

  • [...] int {1,2,3,4,5}

    长度为5的数组,其长度是根据初始化时指定的元素个数决定的

  • [5] int { 2:1,3:2,4:3}

    长度为5的数组,key:value,其元素值依次为:0,0,1,2,3。在初始化时指定了2,3,4索引中对应的值:1,2,3

  • [...] int {2:1,4:3}

    长度为5的数组,起元素值依次为:0,0,1,0,3。由于指定了最大索引4对应的值3,根据初始化的元素个数确定其长度为5

作为参数传递

例如:

package main

import (
        "fmt"
        "reflect"
)

func modifySlice(array []int) {
        array[0] = 10
}

func modifyArr(array [5]int) {
        array[0] = 10
}

func modifyPt(array *[5]int){   // 作为指针传递
    (*array)[0] = 10
}

func main(){
        arr := [...]int{1,2,3,4,5}
        fmt.Println(reflect.TypeOf(arr))
        modifyArr(arr)
        fmt.Println("In main(), arr values:", arr)
        modifyPt(&arr)
        fmt.Println("In main(), arr values:", arr)

        sli := []int{1,2,3,4,5}
        fmt.Println(reflect.TypeOf(sli))
        modifySlice(sli)
        fmt.Println("In main(), sli values:", sli)
}

// 输出结果为
//[5]int
//In main(), arr values: [1 2 3 4 5]
//In main(), arr values: [10 2 3 4 5]
//[]int
//5
//In main(), sli values: [10 2 3 4 5]

slice 切片

从上面的例子中可以看出slice作为参数传递的是指针,因此传递速度会快很多。

但是数组作为一个固定长度的数据类型,在使用中有很多不方便的地方,因此go提供了一个很类似python 中的list的数据类型slice

从名字也能看出来slice支持切片操作

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

还支持append操作

sli = append(sli, 6)
sli = append(sli, sli2)

如果要实现类似数组的值传递的功能,可以利用 copy 函数

sli1 := make([]int, len(sli))
copt(sli1, sli)

初始化

  • 可以通过make初始化
sli := make([]int, 5, 10)  // 5 是其长度,10 是其容量(可选),分别可以通过 len(sli)  cap(sli) 获取
  • 直接初始化(初始长度为0)
var sli []int      // sli = nil
  • 从数组或slice初始化
sli := arr[:]     // sli 的修改也会影响到arr

对比

从上面的内容可以看出数组与切片有以下区别

  • 数组定长,定义的时候就需要确定,切片不定长
  • 切片支持append、copy、切片操作
  • 数组作为参数的时候是默认进行拷贝,值传递,而切片是引用传递

顺便说一下,slice的数据结构类似下面:

+--------------------+

| data pointer |

+--------------------+

| len |

+--------------------+

| cap |

+--------------------+

然后扩容方式与vector类似,1024字节以下是每次cap增加一倍,1024以上是每次cap增加1/4