Go学习之路 (四) 数组和切片

数组的声明

var a [3]int   // 声明并初始化一个数组,最大容量为3,默认为0值
a[0]=1
b := [3]int{1,2,3}            // 声明同时初始化    声明一个容量为3的数组,并且里面存储这1,2,3
c := [2][2]int{{1,2},{3,4}}   // 多维数组初始化

例子:

package main
import "testing"
func TestArrayInit(t *testing.T){
  var arr [3]int         // 创建一个整数数组arr,最大存储为3,这里的int可以改变,根据你的需求改变,如string,这里就是创建一个字符串数组,打印的结果就是三个空
  t.Log(arr[0],arr[1],arr[2])
}

运行结果:

0 0 0
package main
import "testing"
func TestArrayInit(t *testing.T){
  var arr [3]int         
  arr1 := [4]int{1,2,3,4}
  arr3 := [...]int{1,2,3,4,5}   // 这个说明下,这个...是根据数组初始化里的大小来改变的
  t.Log(arr[0],arr[1],arr[2])
}

数组的遍历

// 经典写法
package main
import "testing"
func TestArrayInit(t *testing.T){
  var arr := [...]int{1,2,3,4,5,6,7}
  for i := 0; i < len(arr); i++{
    t.Log(arr[i])
  }
}
// 特性写法
package main
import "testing"
func TestArrayInit(t *testing.T){
  var arr := [...]int{1,2,3,4,5,6,7}
  for idx, e :=range arr3 {
    t.Log(idx, e)         // 这里的idx是索引,e 是值,如果不关心索引,用"_"替换idx("_"是占位符)
  }
}

打印结果:

// 经典写法
1
2
3
4
5
6
7
// Go特性写法(前面个是索引,后面是值)
0 1
1 2
2 3
3 4
4 5
5 6
6 7

数组截取(切片)

  • 切片永远遵循顾头不顾尾[开始索引:结束索引]
    [1:5]真实的是值是[1:5-1]
    [:5]真实的是值是[:5-1]
  • 数组不支持倒着切片
  • 数组也不支持步长
a := [...]int{1,2,3,4,5,6,7}
a[:]    // 1,2,3,4,5,6,7
a[:3]   // 1,2,3
a[1:]   // 2,3,4,5,6,7

切片(slice)

Go学习之路 (四) 数组和切片_第1张图片

首先从左边的从上到下一次是:

  • ptr 指针,指向一片连续的存储空间,也就是指向一个数组
  • len 元素的个数,就是这个切片的元素个数
  • cap 是数组切片分配的空间大小

图片右边的讲解:
有一个长度为5的数组,切片的指针指向了这个数组,总共有5个元素,这个指针指向的数组容量为5

package slice_test
import "testing"
func TestSliceInit(t *testing.T){
  var s0 []int                 // 初始化切片
  t.Log(len(s0),cap(s0)) // cap函数返回的是数组切片分配的空间大小
  s0 = append(s0,1) // 往切片中添加一个值
  t.Log(len(s0),cap(s0)) 
}

输出结果:

0 0
1 1

切片的初始化和数组初始化的不同(切片和数组的初始化特别像)

  • 切片的初始化不需要规定长度,因为切片是一个不定长的
  • 数组的初始化需要规定长度
var s0 []int     // 这个是切片的初始化
var s1 [3]int   // 这个是数组的初始化

切片的声明方法:

var s0 []int
s1 := []int{1,2,3,4}
s2 :=make([]int,3,5)     //make,创建某一种类型变量,第一个参数类型,第二个参数len,第三个参数cap
package slice_test
import "testing"

func TestSliceInit(t *testing.T){
  var s0 []int
  t.Log(len(s0),cap(s0))
  s0 =append(s0,1)
  t.Log(len(s0),cap(s0))
  
  s1 := []int{1,2,3,4,5}
  t.Log(len(s1),cap(s1))
  s2 := make([]int,3,5)
  t.Log(len(s2),cap(s2))
  // t.Log(s2[0],s2[1],s2[2],s2[3],s2[4])   // 这里屏蔽是因为这里会报错,报错内容是 "index out of range" 索引超出范围,原因是make这里我们定义的初始化是长度为3,总容量为5,他只初始化了3个位置,而第四个和第五个没有初始化,(在这里总结为,3为初始化数量,5为总容量)
  s2 = append(s2,1)
  s2 = append(s2,4)
  t.Log(s2[0],s2[1],s2[2],s2[3],s2[4]) 
}

运行结果:

0 0
1 1
5 5
3 5
// index out of range 中间这个报错我也写上
0 0 0 1 4

切片内存的可变长

package slice_test
import "testing"

func TestSliceGrowing(t *testing.T){
  s := []int{}                    // 初始化切片
  for i :=0; i < 10; i++{
    s = append(s,i)           
    t.Log(len(s),cap(s))
  }
}

运行结果

1 1
2 2
3 4
4 4
5 8
6 8
7 8
8 8
9 16
10 16

代码讲解:
首先初始化了一个切片,默认是长度为0,存储空间总容量为0,之后再append数据进去,他的长度增长了, 存储空间容量也增大了,我们可以从结果中看出来,当他的总容量放不下添加进来的数据的时候他会以当前空间总容量乘以二来增大,这里的增大不是之前的空间,而是一个新的空间,这里就是为什么使用的是s = append(s,i),因为切片是不定长的空间,存储进来的数据超过他的大小的时候,他都会重新开辟一块新空间,把原始数据复制进来,然后添加新数据

切片共享存储结构

Go学习之路 (四) 数组和切片_第2张图片

例子

func Test(t *testing.T){
    year :=[] string{"January","February","March","April","May","June","July","August","September","October","November","December"}
    t.Log(year)
    Q2 :=year[4:8]
    t.Log(Q2,len(Q2),cap(Q2))
    summer :=year[7:10]
    t.Log(summer,len(summer),cap(summer))
    summer[0] ="Unknow"
    t.Log(Q2)
    t.Log(summer)
    t.Log(year)
}

运行结果

[January February March April May June July August September October November December]
[May June July August] 4 8
[August September October] 3 5
[May June July Unknow]
[Unknow September October]
[January February March April May June July Unknow September October November December]

这里说明一下,在整个过程中,我们创建了一个切片,并且用切片取出了一些值,在这里切片他只是指向了这个数组的内存空间,(这里解释有些错误,我会更改)

数组和切片的区别

  • 1.容量是否可伸缩
    • 数组是不可伸缩的
    • 切片是可以绳索的
  • 2.是否可以进行比较
    • 数组是在相同维度相同长度下是可以比较的
    • 切片不可比较(会直接报错)

你可能感兴趣的:(Go学习之路 (四) 数组和切片)