数据类型:数组与切片

GO数组特点

  • Go中的数组是值类型

  • 将一个数组赋值给另外一个数组,那么,实际上就是将整个数组拷贝一份

  • 如果Go中的数组作为函数的参数,那么实际传递的参数是一份数组的拷贝,而不是数组的指针。 因此,在Go中如果将数组作为函数的参数传递的话,那效率就肯定没有传递指针高了

  • array的长度也是Type的一部分 [3]int 和 [4]int Type是不一样的,如下代码:

import (
    "fmt"
)

func main() {
    arr01 := [...]int{1, 2, 3}
    arr02 := [...]int{1, 2, 3, 4}
    fmt.Printf("%d 的类型是: %T\n", arr01, arr01)
    fmt.Printf("%d 的类型是: %T", arr02, arr02)
}

输出 如下

[1 2 3] 的类型是: [3]int
[1 2 3 4] 的类型是: [4]int

数组定义

声明数组再赋值

// [3] 里的3 表示该数组的元素个数及容量
var arr [3]int
arr[0] = 1
arr[1] = 2
arr[2] = 3

声明并直接初始化数组 初始化数组的初始化有多种形式,示例代码如下:

arr := [5] int {1,2,3,4,5} 长度为5的数组,其元素值依次为:1,2,3,4,5

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

arr := [...] int {1,2,3,4,5} 长度为5的数组,其长度是根据初始化时指定的元素个数决定的

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

arr := [...] int {2:1,4:3} 长度为5的数组,起元素值依次为:0,0,1,0,3 由于指定了最大索引4对应的值3,根据初始化的元素个数确定其长度为5赋值与使用

定义数组别名类型

每次写[3]int有点麻烦,你可以为[3]int定义一个类型字面量,也就是别名类型

使用type关键字可以定义一个类型字面量,后面只要你想定义一个容器大小为3,元素类型为int的数组 ,都可以使用这个别名类型。代码如下:

import (
    "fmt"
)

func main() {
    type arr3 [3]int

    myarr := arr3{1,2,3}
    fmt.Printf("%d 的类型是: %T", myarr, myarr)
}

输出 如下

[1 2 3] 的类型是: main.arr3

切片

数组的长度不可改变,在特定场景中这样的集合就不太适用

Go中提供了一种灵活,功能强悍的内置类型Slices切片(“动态数组"),* 与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大

切片中有两个概念:一是len长度,二是cap容量,长度是指已经被赋过值的最大下标+1,可通过内置函数len()获得。容量是指切片目前可容纳的最多元素个数,可通过内置函数cap()获得

切片是引用类型,因此在当传递切片时将引用同一指针,修改值将会影响其他的对象

切片初始化

切片可以通过数组来初始化,也可以通过内置函数make()初始化 . 初始化时len=cap,在追加元素时如果容量cap不足时将按len的2倍扩容

  • s :=[] int {1,2,3 } 直接初始化切片,[]表示是切片类型,{1,2,3}初始化值依次是1,2,3.其cap=len=3

  • s := arr[:] 初始化切片s,是数组arr的引用

  • s := arr[startIndex:endIndex] 将arr中从下标startIndex到endIndex-1 下的元素创建为一个新的切片

  • s := arr[startIndex:] 缺省endIndex时将表示一直到arr的最后一个元素

  • s := arr[:endIndex] 缺省startIndex时将表示从arr的第一个元素开始

  • s1 := s[startIndex:endIndex] 通过切片s初始化切片s1

  • s :=make([]int,len,cap) 通过内置函数make()初始化切片s,[]int 标识为其元素类型为int的切片

slice可以从一个数组或一个已经存在的slice中再次声明。slice通过array[i:j]来获取,其中i是数组的开始位置,j是结束位置,但不包含array[j],它的长度是j-i

由于 切片是引用类型,不对它进行赋值的话,它的零值(默认值)是 nil

注意slice和数组在声明时的区别:

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

slice 赋值和使用

  • 切片可以通过内置函数append(slice []Type,elems ...Type)追加元素

  • elems可以是一排type类型的数据,也可以是slice,因为追加的一个一个的元素

  • 如果将一个slice追加到另一个slice中需要带上"...",这样才能表示是将slice中的元素依次追加到另一个slice中

  • 另外在通过下标访问元素时下标不能超过len大小,如同数组的下标不能超出len范围一样。

s := []int{3,2,1}
//一个元素的追加
s =append(s,1,2,3,4)
//将slice中的元素依次追加到另一个slice中
s1 := []int{10,20}
s =append(s,s1...)

import (
   "fmt"
)

func main() {
   myarr := []int{1} // [1]
   // 追加一个元素
   myarr = append(myarr, 2)//[1 2]
   // 追加多个元素
   myarr = append(myarr, 3, 4)//[1 2 3 4]
   // 追加一个切片, ... 表示解包,不能省略
   myarr = append(myarr, []int{7, 8}...)//[1 2 3 4 7 8]
   // 在第一个位置插入元素
   myarr = append([]int{0}, myarr...)//[0 1 2 3 4 7 8]
   // 在中间插入一个切片(两个元素)
   myarr = append(myarr[:5], append([]int{5,6}, myarr[5:]...)...) // [0 1 2 3 4 5 6 7 8]
   fmt.Println(myarr)
}

Last updated

Was this helpful?