您的位置:首页 > 编程语言 > Go语言

go语言数组和切片

2019-03-13 17:21 176 查看

注意: 在 Go 语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。

Go 语言数组的声明

var 数组变量名 [元素数量]T

  • 数组变量名:数组声明及使用时的变量名。
  • 元素数量:数组的元素数量。可以是一个表达式,但最终通过编译期计算的结果必须是整型数值。也就是说,元素数量不能含有到运行时才能确认大小的数值
  • T 可以是任意基本类型,包括 T 为数组本身。但类型为数组本身时,可以实现多维数组。

下面是一段数组的演示例子:

var team [3]string
team[0] = "hammer"
team[1] = "soldier"
team[2] = "mum"
fmt.Println(team)

Go语言数组的初始化

数组可以在声明时使用初始化列表进行元素设置,参考下面的代码:

var team = [3]string{"hammer", "soldier", "mum"}

这种方式编写时,需要保证大括号后面的元素数量与数组的大小一致。但一般情况下,这个过程可以交给编译器,让编译器在编译时,根据元素个数确定数组大小。
var team = [...]string{"hammer", "soldier", "mum"}

…表示让编译器确定数组大小。上面例子中,编译器会自动为这个数组设置元素个数为 3。

Go语言切片

Go 语言切片的内部结构包含地址、大小和容量。切片一般用于快速地操作一块数据集合。如果将数据集合比作切糕的话,切片就是你要的“那一块”。切的过程包含从哪里开始(这个就是切片的地址)及切多大(这个就是切片的大小)。容量可以理解为装切片的口袋大小。
注意: 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型Slices切片(“动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。切片中有两个概念:一是len长度,二是cap容量,长度是指已经被赋过值的最大下标+1,可通过内置函数len()获得。容量是指切片目前可容纳的最多元素个数,可通过内置函数cap()获得。切片是引用类型,因此在当传递切片时将引用同一指针,修改值将会影响其他的对象。

从数组或切片生成新的切片

切片默认指向一段连续内存区域,可以是数组,也可以是切片本身。
从连续内存区域生成切片是常见的操作,格式如下:

slice [开始位置:结束位置]

  • slice 表示目标切片对象。
  • 开始位置对应目标切片对象的索引
  • 结束位置对应目标切片的结束索引
    注意 go语言的切片也是包头不包尾
    从数组生成切片,代码如下:
var a  = [3]int{1, 2, 3}
fmt.Println(a, a[1:2])

注意 数组的最后一个元素可以使用slice[len(slice)] 获取

从指定范围中生成切片

var highRiseBuilding [30]int
for i := 0; i < 30; i++ {
highRiseBuilding[i] = i + 1
}
// 区间
fmt.Println(highRiseBuilding[10:15])
// 中间到尾部的所有元素
fmt.Println(highRiseBuilding[20:])
// 开头到中间的所有元素
fmt.Println(highRiseBuilding[:2])

重置切片,清空拥有的元素

把切片的开始和结束位置都设为 0 时,生成的切片将变空,代码如下:

a := []int{1, 2, 3}
fmt.Println(a[0:0])

代码输出如下:

[]

切片的初始化

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的切片

使用 make() 函数构造切片

如果需要动态地创建一个切片,可以使用 make() 内建函数,格式如下:

make( []T, size, cap )

  • T:切片的元素类型。
  • size:就是为这个类型分配多少个元素。
  • cap:预分配的元素数量,这个值设定后不影响 size,只是能提前分配空间,降低多次分配空间造成的性能问题。
a := make([]int, 2)
b := make([]int, 2, 10)
fmt.Println(a, b)
fmt.Println(len(a), len(b))

代码输出如下:

[0 0] [0 0]
2 2

a 和 b 均是预分配 2 个元素的切片,只是 b 的内部存储空间已经分配了 10 个,但实际使用了 2 个元素。

Go语言append()为切片添加元素

Go 语言的内建函数 append() 可以为切片动态添加元素。每个切片会指向一片内存空间,这片空间能容纳一定数量的元素。当空间不能容纳足够多的元素时,切片就会进行“扩容”。“扩容”操作往往发生在 append() 函数调用时。
切片在扩容时,容量的扩展规律按容量的 2 倍数扩充,例如 1、2、4、8、16……,代码如下:

var numbers []int
for i := 0; i < 10; i++ {
numbers = append(numbers, i)
fmt.Printf("len: %d  cap: %d pointer: %p\n", len(numbers), cap(numbers), numbers)
}

使用 len() 函数查看切片拥有的元素个数,使用 cap() 函数查看切片的容量情况。
append() 函数除了添加一个元素外,也可以一次性添加很多元素。

var car []string

// 添加1个元素
car = append(car, "OldDriver")

// 添加多个元素
car = append(car, "Ice", "Sniper", "Monk")
// 添加切片
team := []string{"Pig", "Flyingcake", "Chicken"}
car = append(car, team...)
fmt.Println(car)

go语言copy()

使用 Go 语言内建的 copy() 函数,可以迅速地将一个数组的数据复制到另外一个数组空间中,copy() 函数的使用格式如下:

copy( destSlice, srcSlice []T) int

  • srcSlice 为数据来源切片。
  • destSlice 为复制的目标。目标切片必须分配过空间且足够承载复制的元素个数。来源和目标的类型一致,copy 的返回值表示实际发生复制的元素个数。

下面的代码将演示对切片的引用和复制操作后对切片元素的影响。

package main
import "fmt"
func main() {
// 设置元素数量为1000
const elementCount = 1000
// 预分配足够多的元素切片
srcData := make([]int, elementCount)
// 将切片赋值
for i := 0; i < elementCount; i++ {
srcData[i] = i
}
// 引用切片数据
refData := srcData
// 预分配足够多的元素切片
copyData := make([]int, elementCount)
// 将数据复制到新的切片空间中
copy(copyData, srcData)
// 修改原始数据的第一个元素
srcData[0] = 999
// 打印引用切片的第一个元素
fmt.Println(refData[0])
// 打印复制切片的第一个和最后一个元素
fmt.Println(copyData[0], copyData[elementCount-1])
// 复制原始数据从4到6(不包含)
copy(copyData, srcData[4:6])
for i := 0; i < 5; i++ {
fmt.Printf("%d ", copyData[i])
}
}

Go语言从切片中删除元素

Go 语言并没有对删除切片元素提供专用的语法或者接口,需要使用切片本身的特性来删除元素

seq := []string{"a", "b", "c", "d", "e"}
// 指定删除位置
index := 2
// 查看删除位置之前的元素和之后的元素
fmt.Println(seq[:index], seq[index+1:])
// 将删除点前后的元素连接起来
seq = append(seq[:index], seq[index+1:])
fmt.Println(seq)

注意 append里面可以拼接多段切片
Go 语言中切片删除元素的本质是:以被删除元素为分界点,将前后两个部分的内存重新连接起来。

连续容器的元素删除无论是在任何语言中,都要将删除点前后的元素移动到新的位置。随着元素的增加,这个过程将会变得极为耗时。因此,当业务需要大量、频繁地从一个切片中删除元素时,如果对性能要求较高,就需要反思是否需要更换其他的容器(如双链表等能快速从删除点删除元素)。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: