首先数组是一种数据结构,而Go语言也提供了数组类型的数据结构,数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形、字符串或者自定义类型等。
数组元素可以通过索引(位置)来读取(或者修改),索引从0开始,第一个元素索引为 0,第二个索引为 1,以此类推。数组的下标取值范围是从0开始,到数组长度减1。数组一旦定义后,其大小不能更改。
数组的声明和初始化需要指明其大小和数据类型。
语法格式如下:
var variable_name [SIZE]variable_type
示例代码如下:
var score [10]float32var score = [5]float32{100.0, 2.0, 3.4, 6.0, 40.0}
注意事项:
初始化数组中 {} 中的元素个数不能大于 [] 中的数字
如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小
示例如下:
var score = []float32{100.0, 80.0, 77.5, 89.0, 60.0}score[4] = 90.0
其它创建数据方式如下,相关说见注释:
var a [4] float32 // 等价于:var arr2 = [4]float32{} fmt.Println(a) // [0 0 0 0] var b = [5] string{
"hello", "Jack", "shenzhen"} fmt.Println(b) // [hello hello shenzhen] var c = [5] int{
'A', 'B', 'C', 'D', 'E'} // byte fmt.Println(c) // [65 66 67 68 69] d := [...] int{
1,2,3,4,5}// 根据元素的个数,设置数组的大小 fmt.Println(d) //[1 2 3 4 5] e := [5] int{
4: 100} fmt.Println(e) // [0 0 0 0 100] f := [...] int{
0: 1, 4: 1, 9: 1} fmt.Println(f) // [1 0 0 0 1 0 0 0 0 1]
数组可以根据下标来访问元素,比如:score[1]等。
通过将数组作为参数传递给len函数,可以获得数组的长度。
示例代码:
package mainimport "fmt"func main() { nums := [...]float64{66.7, 88.8, 22, 68} // nums := [...]int{12, 78, 50} //方式二 fmt.Println("length of nums is",len(a))}
输出结果:
length of nums is 4
package mainimport "fmt"func main() { a := [...]float64{67.7, 89.8, 21, 78} for i := 0; i < len(a); i++ { // 循环遍历从0到数组长度,获取数组元素 fmt.Printf("%d th element of a is %.2f\n", i, a[i]) }}
package mainimport "fmt"func main() { a := [...]float64{67.7, 89.8, 21, 78} for index, value := range a { // 循环遍历从0到数组长度,获取数组元素 fmt.Printf("%d th element of a is %.2f\n", index, value) }}
如果您只需要值并希望忽略索引,那么可以通过使用 “_” 标识符替换索引来实现这一点。 示例如下:
for _, v := range a { // 忽略索引}
另外需要注意的是:
Go中的数组是值类型,而不是引用类型。这意味着当它们被分配给一个新变量时,将把原始数组的副本分配给新变量。如果对新变量进行了更改,则不会在原始数组中反映。
package mainimport "fmt"func main() { a := [...]string{"USA", "China", "France"} b := a // 这里 a 会拷贝一份给b b[0] = "Japan" fmt.Println("a is ", a) fmt.Println("b is ", b) }
输出打印结果如下,可以看到 a 的结果没有被修改:
a is [USA China France] b is [Japan China France]
数组的大小是类型的一部分。因此[5]int和[25]int是不同的类型。因此,数组不能被调整大小,而切片的存在是为了解决这个问题。
在Go语言中,可以说切片是对数组的抽象。数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
切片与数组相比,不需要设定长度,在[]中不用设定值,相对来说比较自由,从概念上面来说 slice 像一个结构体,这个结构体包含了三个元素:
指针,指向数组中slice指定的开始位置
长度,即切片中可访问的元素长度
容量,也就是slice开始位置到数组的最后位置的长度
定义切片的语法,切片不需要说明长度:
var identifier []type
或者可以用 make 来定义:
var slice1 []type = make([]type, len)// 也可以简写为slice1 := make([]type, len)// 或 make([]T, length, capacity)
切片初始化及使用示例如下:
package mainimport ( "fmt")func main() { a := [5]int{76, 77, 78, 79, 80} // 从数组变量 a[1] to a[3] 创建新的切片变量 b var b []int = a[1:4] //creates a slice from a[1] to a[3] fmt.Println(b) // [77 78 79]}
slice没有自己的任何数据。它只是底层数组的一个表示。对slice所做的任何修改都将反映在底层数组中。
(修改切片)示例代码如下:
package mainimport ( "fmt")func main() { darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59} dslice := darr[2:5] fmt.Println("array before",darr) for i := range dslice {
dslice[i]++ } fmt.Println("array after",darr) }
输出结果:
array before [57 89 90 82 100 78 67 69 59]array after [57 89 91 83 101 78 67 69 59]
切片的长度是切片中元素的数量。切片的容量是从创建切片的索引开始的底层数组中元素的数量。
切片是可索引的,并且可以由 len() 方法获取长度
切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少
package mainimport "fmt"func main() {
var numbers = make([]int,3,5) printSlice(numbers)}func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)}
输出结果:
len=3 cap=5 slice=[0 0 0]
注:一个切片在未初始化之前默认为 nil,长度为 0。
append 向slice里面追加一个或者多个元素,然后返回一个和slice一样类型的slice。
copy 函数copy从源slice的src中复制元素到目标dst,并且返回复制的元素的个数。
append函数会改变slice所引用的数组的内容,从而影响到引用同一数组的其它slice。但当slice中没有剩余空间(即(cap-len) == 0)时,此时将动态分配新的数组空间。返回的slice数组指针将指向这个空间,而原数组的内容将保持不变;其它引用此数组的slice则不受影响。
copy 方法和append 方法使用示例代码如下:
package mainimport "fmt"func main() {
var numbers []int printSlice(numbers) /* 允许追加空切片 */ numbers = append(numbers, 0) printSlice(numbers) /* 向切片添加一个元素 */ numbers = append(numbers, 1) printSlice(numbers) /* 同时添加多个元素 */ numbers = append(numbers, 2,3,4) printSlice(numbers) /* 创建切片 numbers1 是之前切片的两倍容量*/ numbers1 := make([]int, len(numbers), (cap(numbers))*2) /* 拷贝 numbers 的内容到 numbers1 */ copy(numbers1,numbers) printSlice(numbers1) }func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)}
打印结果如下:
len=0 cap=0 slice=[]len=1 cap=2 slice=[0]len=2 cap=2 slice=[0 1]len=5 cap=8 slice=[0 1 2 3 4]len=5 cap=12 slice=[0 1 2 3 4]
以上示例代码已归档到我的github,如有需要欢迎下载学习交流:https://github.com/Scoefield/gokeyboardman/tree/main/arrayslice
本次有关Golang数组和切片的介绍就到这里啦,感谢您的阅读,如有疑问或意见请及时反馈给我们。
上一篇文章:
Golang中的流程语句