go语言数组和切片
注意: 在 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 语言中切片删除元素的本质是:以被删除元素为分界点,将前后两个部分的内存重新连接起来。
连续容器的元素删除无论是在任何语言中,都要将删除点前后的元素移动到新的位置。随着元素的增加,这个过程将会变得极为耗时。因此,当业务需要大量、频繁地从一个切片中删除元素时,如果对性能要求较高,就需要反思是否需要更换其他的容器(如双链表等能快速从删除点删除元素)。
- GO语言总结(3)——数组和切片
- Golang(Go语言)代码技巧之数组(array)和切片(slice)
- Go语言数组和切片的原理
- Go语言学习笔记四--数组与切片
- golang中的数组与切片
- 【python学习笔记】19:numpy数组布尔运算和切片
- Go语言入门——数组、切片和映射
- [翻译] NumSharp的数组切片功能 [:]
- 关于Go语言数组索引的有趣现象
- GO语言数组和切片实例详解
- Go语言学习五:数组与传递到函数的数组
- numpy中的数组切片
- go语言之行--数组、切片、map
- Go语言_数组_Go语言创建、初始化数组的常见方式汇总
- go 数组(array)、切片(slice)、map、结构体(struct)
- php实现有序数组打印或排序的方法【附Python、C及Go语言实现代码】
- Pyhton科学计算工具Numpy(二)之数组索引切片,numpy随机数及文件生成读取
- 理解Golang中的数组(array)、切片(slice)和map
- python numpy多维数组切片问题
- python 基础语法之列表、n维数组的变换(取反(逆序)\切片等)