• go语言之数组,切片,字典


    数组申明方式:

            var ip4 [7]uint8 = [7]uint8{1, 2, 3, 4, 5}

            for i, value := range ip4 {

                     fmt.Printf("index=%d,value=%d ", i, value)

            }

    数组和切片slice的区别:

    Slice切片是对底层数组Array的封装,在内存中的存储本质就是数组,体现为连续的内存块,Go语言中的数组定义之后,长度就已经固定了,在使用过程中并不能改变其长度,而Slice就可以看做一个长度可变的数组进行使用,最为关键的,是数组在使用的过程中都是值传递,将一个数组赋值给一个新变量或作为方法参数传递时,是将源数组在内存中完全复制了一份,而不是引用源数组在内存中的地址,为了满足内存空间的复用和数组元素的值的一致性的应用需求,Slice出现了,每个Slice都是都源数组在内存中的地址的一个引用,源数组可以衍生出多个Slice,Slice也可以继续衍生Slice,而内存中,始终只有源数组,当然,也有例外。

    Slice的定义:

    Slice可以通过两种方式定义,一种是从源数组中衍生,一种是通过make函数定义,本质上来说都一样,都是在内存中通过数组的初始化的方式开辟一块内存,将其划分为若干个小块用来存储数组元素,然后Slice就去引用整个或者局部数组元素。

    比如s:=[]int{1,2,3}

    注意,这与初始化数组有一点点区别,可能有人认为这个写法是定义和初始化一个数组,事实上这个写法是现在内存中构建一个包括有3个元素的数组,然后将这个数组的应用赋值给s这个Slice,通过以下数组的定义进行区别:

    a := [3]int{1, 2, 3}
     b := [...]int{1, 2, 3}
     c := []int{1, 2, 3}
     fmt.Println(cap(a), cap(b), cap(c))
     a = append(a, 4)//Error:first argument to append must be slice; have [3]int
     b = append(b, 4)//Errot:first argument to append must be slice; have [3]int
     c = append(c, 4)//正常,说明变量c是Slice类型

    可以看出,强调了数组定义的规则:长度和类型必须指定,若是根据实际元素个数自动计算数组长度,需要使用[...]定义,而不能只使用[]。

     

     

    从数组切片中创建slice:

    a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
     s := a[2:8]
     fmt.Println(s) //输出:[3 4 5 6 7 8]

     

    通过make函数创建一个slice

    s := make([]int, 10, 20)
     fmt.Println(s) //输出:[0 0 0 0 0 0 0 0 0 0]

     

    make函数第一个参数表示构建的数组的类型,第二个参数为数组的长度,第三个参数可选,是slice的容量,默认为第二个参数值。

     

    Slice的长度和容量

    Slice有两个比较混淆的概念,就是长度和容量,何谓长度?这个长度跟数组的长度是一个概念,即在内存中进行了初始化实际存在的元素的个数。何谓容量?如果通过make函数创建Slice的时候指定了容量参数,那内存管理器会根据指定的容量的值先划分一块内存空间,然后才在其中存放有数组元素,多余部分处于空闲状态,在Slice上追加元素的时候,首先会放到这块空闲的内存中,如果添加的参数个数超过了容量值,内存管理器会重新划分一块容量值为原容量值*2大小的内存空间,依次类推。这个机制的好处在能够提升运算性能,因为内存的重新划分会降低性能。


    Slice是引用类型

    上边已经提到过,Slice是对源数组的一个引用,改变Slice中的元素的值,实质上就是改变源数组的元素的值

    a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
     sa := a[2:7]
     sa = append(sa, 100)
     sb := sa[3:8]
     sb[0] = 99
     fmt.Println(a)  //输出:[1 2 3 4 5 99 7 100 9 0]
     fmt.Println(sa) //输出:[3 4 5 99 7 100]
     fmt.Println(sb) //输出:[99 7 100 9 0]

     

    可以看到,不管是append操作,还是赋值操作,都影响了源数组或者其他引用同一数组的Slice的元素。Slice进行数组引用的时候,其实是将指针指向了内存中具体元素的地址,如数组的内存地址,事实上是数组中第一个元素的内存地址,Slice也是如此。

     

    a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
     sa := a[2:7]
     sb := sa[3:8]
     fmt.Printf("%p ", sa)   //输出:0xc084004290
     fmt.Println(&a[2], &sa[0])      //输出:0xc084004290 0xc084004290
     fmt.Printf("%p ", sb)   //输出:0xc0840042a8
     fmt.Println(&a[5], &sb[0])      //输出:0xc0840042a8 0xc0840042a8

     

    Slice引用传递发生意外:

    上边我们一直在说,Slice是引用类型,指向的都是内存中的同一块内存,不过在实际应用中,有的时候却会发生“意外”,这种情况只有在像切片append元素的时候出现,Slice的处理机制是这样的,当Slice的容量还有空闲的时候,append进来的元素会直接使用空闲的容量空间,但是一旦append进来的元素个数超过了原来指定容量值的时候,内存管理器就是重新开辟一个更大的内存空间,用于存储多出来的元素,并且会将原来的元素复制一份,放到这块新开辟的内存空间。

     

     a := []int{1, 2, 3, 4}
     sa := a[1:3]
     fmt.Printf("%p ", sa) //输出:0xc0840046e0
     sa = append(sa, 11, 22, 33)
     fmt.Printf("%p ", sa) //输出:0xc084003200

     

    字典:有如下几种申明方式。

            方法一:直接make创建一个字典,map[string]int代表键值类型为string,value类型为int,字典长度为4个。

    var ipswitch = make(map[string]int, 4)

            ipswitch["abc"] = 1

            方法二:直接申明map创建一个字典,注意后面需要带{},然后进行赋值

            var ipswitch_update = map[string]int{}

            ipswitch_update["abc"] = 2

            ipswitch_update["country"] = 3

            ipswitch_update["color"] = 4

            ipswitch_update["city"] = 5

            ipswitch_update["house"] = 6

            方法三:在申明的同时进行字典的初始化

            var ipswitch_new = map[string]int{"country": 1, "city": 2, "school": 3}

           

            字典的遍历

            for key := range ipswitch_update {

                     fmt.Println(key, " value=", ipswitch_update[key])

            }

     

            for key := range ipswitch_new {

                     fmt.Println(key, " value=", ipswitch_new[key])

            }

  • 相关阅读:
    Java并发2
    使用Redis锁可能出现的问题
    社区项目前端vue总结
    社区项目Redis分布式锁穿透击穿雪崩
    社区项目遇到的问题
    html2canvas 下载的图片有空白 Amy
    html2canvas 支持backgroundClip:text Amy
    查看nacvicate连接数据库密码
    CPU飙升问题排查
    vue3 学习笔记
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/13880371.html
Copyright © 2020-2023  润新知