切片 里面包含interface_Golang的数组和切片

f38d050ef9b160f6bb90095589231fdb.gif

切片 里面包含interface_Golang的数组和切片_第1张图片

什么是数组

首先数组是一种数据结构,而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])    }}
  • 当遍历方式二,使用range遍历数组

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)    }}

其中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()函数

切片的长度是切片中元素的数量。切片的容量是从创建切片的索引开始的底层数组中元素的数量。

  • 切片是可索引的,并且可以由 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()和copy()函数

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中的流程语句

你可能感兴趣的:(切片,里面包含interface)