Go语言基础之数组 切片和映射

Go语言基础之数组 切片 和映射

数组

数组:相同类型的一组数据,一旦定义之后,大小不能发生改变

下面是操作数组的一些栗子

 func test( a[5] int) int {   //数组作参数时必须规定大小和类型
    return a[0]
 }
 func main() {
    //几种声明和初始化数组的方式
 ​
 ​
    var a [5] int   //仅声明
    a[0],a[1],a[2]=3,4,5
    fmt.Println(a,len(a),cap(a))
 ​
 ​
    var b =[5] int {1,2,3} //声明的时候初始化 注意数值个数必须比数组大小要小
    fmt.Println(b,len(b),len(b))
 ​
 ​
    var c=[] int {1,2,3,4} //不规定大小的初始化,Go自动根据个数设置大小
    fmt.Println(c,len(c),cap(c))
 ​
 ​
    d:=[] float64{5.0,6.0,7.0}
    fmt.Println(d,len(d),cap(d))
 ​
 ​
    e:=[...] int{0:2,5:9,9:11} //在特定位置赋值
    fmt.Println(e,len(e),cap(e))
 ​
 ​
    //数组是值类型,对赋值的新变量进行修改,不会在原始数组中表现出来
    f:=a
    f[0]=999
    fmt.Println(a,len(a),cap(a))
    fmt.Println(f,len(f),cap(f))
 ​
 ​
    //多维数组
    var n =[2][2]int {{1,2},{3,4}}
    fmt.Println(n,len(n),cap(n))
 ​
 ​
    //多维数组的遍历
    for _,v :=range n {
        for _,v2:= range v {
          fmt.Println(v,v2)
      }
    }
 ​
 ​
    //数组作为参数
    fmt.Println(test(a),test(b))
 }
 //
 输出:
 [3 4 5 0 0] 5 5
 [1 2 3 0 0] 5 5
 [1 2 3 4] 4 4
 [5 6 7] 3 3
 [2 0 0 0 0 9 0 0 0 11] 10 10
 [3 4 5 0 0] 5 5
 [999 4 5 0 0] 5 5
 [[1 2] [3 4]] 2 2
 [1 2] 1
 [1 2] 2
 [3 4] 3
 [3 4] 4
 3 1

 

注意:

  • 遍历数组的两种方式分别是for i<len(arraryname)和 for range **

  • 数组是值类型

  • 数组作为形参要规定长度

  • 数组支持逻辑运算符== !=等,其中==成立的数组,每个元素的值都要等

  • [n] * type表示指针数组,* [n] type 表示数组指针

  • 对数组使用[:]冒号运算符的时候,其实是通过指针进入到数组里数据的地址,对其进行拷贝或者修改,也就是说修改截取之后新的数组的值,是会改变原数组的值的

切片

切片:Go的切片是对数组的抽象,与数组相比,切片的长度是不固定的。可以追加元素(不仅增加了切片的len也增加了cap),本质是封装好的数组,包含了三个信息:底层数组的指针,切片的长度和切片的容量

关于切片的一些操作

 func main()  {
    var a [] int
    b:=make([]int,10) // 10为length
    b[0]=2
    c:=make([]int,10,20) //10为length ,20为cap]
    d:=[] int {2,3,4,5,6,7,8,9,0,1}
 ​
 ​
    /*a[0]=1
    a[1]=2
    a[2]=3 */   //当声明了切片 却没有给len的时候,再进行赋值是会报错的
    //因为我们声明了却没有实例化 那么len和cap都是0 赋值的过程相当于下标溢出
    a=append(a,1) //用append塞进去是对的
 ​
 ​
    //: 运算符
    fmt.Println(d[:])
    e:=d[1:4]//d[1] 到 d[3] 即 3 4 5
    fmt.Println(e,len(e),cap(e))
    fmt.Println(len(a),cap(a))
    fmt.Println(len(b),cap(b))
    fmt.Println(len(c),cap(c)) //len是切片中元素的数量 cap是从创建切片的索引开始的底层数组中元素的数量
 ​
 ​
 ​
 ​
    //更改切片的值 因为切片是引用传递 所有相关的副本都会反映出来
    d[1]=20
    fmt.Println(d[:])
    fmt.Println(e[:])
 ​
 ​
 ​
 ​
    copy(c,b) //把b的值拷贝到c中
    b[0]=1
    fmt.Println(b)
    fmt.Println(c)   //copy之后改变原来的slice的值,是不会对新slice产生影响的
 }
检查切片是否为空
 var s1 []int         //len(s1)=0;cap(s1)=0;s1==nil
 s2 := []int{}       //len(s2)=0;cap(s2)=0;s2!=nil 因为已经初始化数组了
 s3 := make([]int, 0) //len(s3)=0;cap(s3)=0;s3!=nil
 //应该用len(s)==0 判断,而不是s==nil
比较两个切片

引用类型是不能直接比较的,只能和nil进行比较,值类型是可以直接比较的

删除切片的方法
 要从切片a中删除索引为index的元素,操作方法是a = append(a[:index], a[index+1:]...) //要把一个切片append到另一个切片里 一定要写... 
 //把一个数或者几个数往slice里面append可以直接写
 //把slice往slice里面塞,后缀一定要用...
切片的复制

我们可以用等号直接将一个切片赋值给另一个切片,但是这不是值传递,而是引用传递,即一个切片的值被修改,另一个切片的值也会被修改,原因是因为这两个切片的地址是一致的,想要做到真正的复制只能使用copy函数

映射

映射:Go中的内置类型,它将一个值和一个键关联起来,底层实现是hash,是一种无序的键值对集合,也是引用类型

一些栗子

 func main()  {        
    //初始化map
    //1.make
    map1:=make(map[int]string)
    fmt.Println(len(map1)) //0
    fmt.Println(map1==nil)   //flase make创建引用类型时默认初始化
    map1[1]="爱小黄"    
    map1[0]="爱妈妈"
    map1[2]="爱爸爸"                            
    fmt.Println(map1,len(map1)) //len=3,即键值对的个数
    v,ok:=map1[0]
    fmt.Println(v,ok)   //v 是value ,ok 是判断是否存在的bool值
    delete(map1,0)//删除map1为0的索引值
    fmt.Println(map1)                                        
    //2.:map的方式初始化Map
    map2:=map[int]string{1:"爱你"}
    fmt.Println(map2)
    //map是不能拷贝的,我们想拥有一个一模一样的map只能用for range然后赋值的方式
 }
注意:
  • map打印的时候是无序输出的,因为底层实现是hash

  • 删除Map中的某一个值,使用delete函数

  • Map不能使用copy函数,想要进行Map的复制只能通过for range的方式手动赋值

  • 无论是slice array还是map等数据类型,我们在声明的时候都是没有占据内存的,也就是并没有实例化,而如果我们使用Make函数,哪怕cap是0,也是已经分配内存了的

     

  •  

 

上一篇:OPENCV FOR PYTHON 学习笔记 - VideoCapture


下一篇:教你解决线上频出MySQL死锁问题!含BATJM大厂