导航

Go语言中的数组(array)和数组切片(slice)

Posted on 2013-02-17 18:31  蝈蝈俊  阅读(3938)  评论(0编辑  收藏  举报

        在Go语言中,数组长度在定义后就不可更改,在声明时长度可以为一个常量或者一个常量表达式(常量表达式是指在编译期即可计算结果的表达式)。数组的长度是该数组类型的一个内置常量,可以用Go语言的内置函数len()来获取。

        数组的长度在定义后无法再次修改;数组是值类型,每次传递都产生一份副本。

        初看起来数组切片就像一个指向数组的指针,实际上它拥有自己的数据结构,而不仅仅是一个指针。数组切片的数据结构可以抽象为以下3个变量:

  • 一个指向原生数组的指针
  • 数组切片中元素的个数
  • 数组切片已分配的存储空间

        从底层实现的角度看,数组切片实际上仍然使用数组来管理元素,基于数组,数组切片添加了一系列管理功能,可以随时动态扩充存放空间,并且可以被随意传递,而不会导致所管理的元素被复制。

下面用 reflect 包来反射出数据的类型。

package main
 
import(
    "fmt"
    "reflect"
)
 
func main(){
 
    vs:=[]interface{}{
        []int{},// slice 切片
        []int{1,2,3},// slice 切片
        []int{1,2,3}[:],//切片再切还是切片
        make([]int,3,10),//标准的slice 定义方式
        [3]int{1,2,3},//array 数组,确定数组长度
        [...]int{1,2,3},//array 数组,由编译器自动计算数组长度。
    }
    for i,v:=range vs{
        rv:=reflect.ValueOf(v)//进入疯狂的reflect世界
        fmt.Println(i,rv.Kind())
    }
}

上述程序执行结果:

0 slice

1 slice

2 slice

3 slice

4 array

5 array

注意slice和数组在声明时的区别:声明数组时,方括号内写明了数组的长度或使用...自动计算长度,而声明slice时,方括号内没有任何字符。

数组切片的扩容:

 

    ww:=make([]int,3,5)
    ww[0]=23
    ww[1]=23
    ww[2]=23
    //ww[3]=34// 这样赋值会报错误 panic: runtime error: index out of range 超过了切片的大小
 
    fmt.Println(cap(ww))
    ww=append(ww,2,4,34)//需要用 append 给赋值, append 在存储空间不足时,会自动增加存储空间
    fmt.Println(cap(ww))
    fmt.Println(ww)

注:append函数会改变slice所引用的数组的内容,从而影响到引用同一数组的其它slice。 但当slice中没有剩余空间(即(cap-len) == 0)时,此时将动态分配新的数组空间。返回的slice数组指针将指向这个空间,而原数组的内容将保持不变;其它引用此数组的slice则不受影响。

 

 

参考:
数组(Array)和切片(Slice)
http://my.oschina.net/lxpan/blog/87432 

Golang Go语言Array数组与Slice切片的不同
http://kejibo.com/golang-slice-array-reflect/

2.2 Go基础 
https://github.com/astaxie/build-web-application-with-golang/blob/master/02.2.md